pycoast 1.1.0__py3-none-any.whl → 1.7.1__py3-none-any.whl
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.
- pycoast/__init__.py +29 -9
- pycoast/conftest.py +14 -0
- pycoast/cw_agg.py +762 -468
- pycoast/cw_base.py +1575 -768
- pycoast/cw_pil.py +583 -363
- pycoast/tests/__init__.py +19 -0
- pycoast/tests/brazil_shapefiles.png +0 -0
- pycoast/tests/brazil_shapefiles_agg.png +0 -0
- pycoast/tests/coasts_and_grid.ini +13 -0
- pycoast/tests/coasts_and_grid_agg.ini +17 -0
- pycoast/tests/contours_europe.png +0 -0
- pycoast/tests/contours_europe_agg.png +0 -0
- pycoast/tests/contours_europe_alpha.png +0 -0
- pycoast/tests/contours_geos.png +0 -0
- pycoast/tests/contours_geos_agg.png +0 -0
- pycoast/tests/dateline_boundary_cross.png +0 -0
- pycoast/tests/dateline_cross.png +0 -0
- pycoast/tests/eastern_shapes_agg.png +0 -0
- pycoast/tests/eastern_shapes_pil.png +0 -0
- pycoast/tests/grid_europe.png +0 -0
- pycoast/tests/grid_europe_agg.png +0 -0
- pycoast/tests/grid_europe_agg_txt.png +0 -0
- pycoast/tests/grid_from_dict_agg.png +0 -0
- pycoast/tests/grid_from_dict_pil.png +0 -0
- pycoast/tests/grid_geos.png +0 -0
- pycoast/tests/grid_geos_agg.png +0 -0
- pycoast/tests/grid_germ.png +0 -0
- pycoast/tests/grid_nh.png +0 -0
- pycoast/tests/grid_nh_agg.png +0 -0
- pycoast/tests/grid_nh_cfg_agg.png +0 -0
- pycoast/tests/lonlat_boundary_cross.png +0 -0
- pycoast/tests/nh_cities_agg.ini +26 -0
- pycoast/tests/nh_cities_agg.png +0 -0
- pycoast/tests/nh_cities_from_dict_agg.png +0 -0
- pycoast/tests/nh_cities_from_dict_pil.png +0 -0
- pycoast/tests/nh_cities_pil.ini +20 -0
- pycoast/tests/nh_cities_pil.png +0 -0
- pycoast/tests/nh_one_shapefile.ini +11 -0
- pycoast/tests/nh_points_agg.ini +24 -0
- pycoast/tests/nh_points_agg.png +0 -0
- pycoast/tests/nh_points_cfg_pil.png +0 -0
- pycoast/tests/nh_points_pil.ini +19 -0
- pycoast/tests/nh_points_pil.png +0 -0
- pycoast/tests/nh_polygons.png +0 -0
- pycoast/tests/nh_polygons_agg.png +0 -0
- pycoast/tests/no_h_scratch_agg.png +0 -0
- pycoast/tests/no_h_scratch_pil.png +0 -0
- pycoast/tests/no_v_scratch_agg.png +0 -0
- pycoast/tests/no_v_scratch_pil.png +0 -0
- pycoast/tests/one_shapefile_from_cfg_agg.png +0 -0
- pycoast/tests/one_shapefile_from_cfg_pil.png +0 -0
- pycoast/tests/test_data/DejaVuSerif.ttf +0 -0
- pycoast/tests/test_data/gshhs/CITIES/cities.txt +20 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.dbf +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.prj +1 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.shp +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L1.shx +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.dbf +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.prj +1 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.shp +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L2.shx +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.dbf +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.prj +1 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.shp +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L3.shx +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.dbf +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.prj +1 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.shp +0 -0
- pycoast/tests/test_data/gshhs/GSHHS_shp/l/GSHHS_l_L4.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L1.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L2.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_border_c_L3.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L01.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L02.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L03.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L04.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L05.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L06.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L07.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L08.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L09.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L1.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L1.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L1.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L10.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.prj +1 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L11.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L2.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L2.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L2.shx +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L3.dbf +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L3.shp +0 -0
- pycoast/tests/test_data/gshhs/WDBII_shp/c/WDBII_river_c_L3.shx +0 -0
- pycoast/tests/test_data/shapes/Metareas.dbf +0 -0
- pycoast/tests/test_data/shapes/Metareas.mxd +0 -0
- pycoast/tests/test_data/shapes/Metareas.prj +1 -0
- pycoast/tests/test_data/shapes/Metareas.sbn +0 -0
- pycoast/tests/test_data/shapes/Metareas.sbx +0 -0
- pycoast/tests/test_data/shapes/Metareas.shp +0 -0
- pycoast/tests/test_data/shapes/Metareas.shx +0 -0
- pycoast/tests/test_data/shapes/README +3 -0
- pycoast/tests/test_data/shapes/divisao_politica/BRASIL.dbf +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BRASIL.shp +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BRASIL.shx +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Capitais.dbf +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Capitais.shp +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Capitais.shx +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Contorno.dbf +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Contorno.shp +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Contorno.shx +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Regioes.dbf +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Regioes.shp +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/BR_Regioes.shx +0 -0
- pycoast/tests/test_data/shapes/divisao_politica/divisao_politica.txt +40 -0
- pycoast/tests/test_data/shapes/divisao_politica/leia.txt +9 -0
- pycoast/tests/test_data/shapes/metarea5.gsf +0 -0
- pycoast/tests/test_data/shapes/metarea5.tbl +21 -0
- pycoast/tests/test_data/shapes/metarea5.tbl.info +25 -0
- pycoast/tests/test_data/test_config.ini +12 -0
- pycoast/tests/test_pycoast.py +1916 -419
- pycoast/tests/two_shapefiles_agg.png +0 -0
- pycoast/tests/two_shapefiles_pil.png +0 -0
- pycoast/tests/western_shapes_agg.png +0 -0
- pycoast/tests/western_shapes_pil.png +0 -0
- pycoast/version.py +19 -17
- pycoast-1.7.1.dist-info/AUTHORS.md +20 -0
- pycoast-1.7.1.dist-info/LICENSE.txt +674 -0
- pycoast-1.7.1.dist-info/METADATA +81 -0
- pycoast-1.7.1.dist-info/RECORD +172 -0
- {pycoast-1.1.0.dist-info → pycoast-1.7.1.dist-info}/WHEEL +1 -1
- pycoast-1.1.0.dist-info/DESCRIPTION.rst +0 -3
- pycoast-1.1.0.dist-info/METADATA +0 -24
- pycoast-1.1.0.dist-info/RECORD +0 -13
- pycoast-1.1.0.dist-info/metadata.json +0 -1
- {pycoast-1.1.0.dist-info → pycoast-1.7.1.dist-info}/top_level.txt +0 -0
pycoast/tests/test_pycoast.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
1
3
|
# pycoast, Writing of coastlines, borders and rivers to images in Python
|
|
2
4
|
#
|
|
3
|
-
# Copyright (C) 2011
|
|
5
|
+
# Copyright (C) 2011-2020 PyCoast Developers
|
|
4
6
|
#
|
|
5
7
|
# This program is free software: you can redistribute it and/or modify
|
|
6
8
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -14,30 +16,50 @@
|
|
|
14
16
|
#
|
|
15
17
|
# You should have received a copy of the GNU General Public License
|
|
16
18
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
"""Main unit tests for pycoast."""
|
|
17
20
|
|
|
18
21
|
import os
|
|
19
|
-
import
|
|
22
|
+
import pathlib
|
|
23
|
+
import time
|
|
24
|
+
from glob import glob
|
|
20
25
|
|
|
26
|
+
import aggdraw
|
|
21
27
|
import numpy as np
|
|
28
|
+
import pytest
|
|
29
|
+
import shapefile
|
|
22
30
|
from PIL import Image, ImageFont
|
|
31
|
+
from pyproj import CRS
|
|
32
|
+
from pyresample.geometry import AreaDefinition
|
|
33
|
+
from pytest_lazy_fixtures import lf as lazy_fixture
|
|
23
34
|
|
|
24
|
-
|
|
35
|
+
LOCAL_DIR = os.path.dirname(__file__)
|
|
25
36
|
|
|
37
|
+
gshhs_root_dir = os.path.join(LOCAL_DIR, "test_data", "gshhs")
|
|
38
|
+
repos_root_dir = os.path.join(LOCAL_DIR, "..", "..")
|
|
39
|
+
test_filename = "test_image.png"
|
|
40
|
+
grid_filename = "test_grid.png"
|
|
41
|
+
p_coasts_filename = "test_coasts_p_mode.png"
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
font_path = os.path.join(LOCAL_DIR, "test_data", "DejaVuSerif.ttf")
|
|
44
|
+
agg_font_20_yellow = aggdraw.Font("yellow", font_path, opacity=255, size=20)
|
|
45
|
+
agg_font_20_orange = aggdraw.Font("orange", font_path, opacity=255, size=20)
|
|
46
|
+
pil_font_20 = ImageFont.truetype(font_path, 20)
|
|
47
|
+
pil_font_16 = ImageFont.truetype(font_path, 16)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.fixture
|
|
51
|
+
def cd_test_dir(monkeypatch):
|
|
52
|
+
"""Change directory to the pycoast/tests directory."""
|
|
53
|
+
monkeypatch.chdir(LOCAL_DIR)
|
|
30
54
|
|
|
31
55
|
|
|
32
56
|
def fft_proj_rms(a1, a2):
|
|
33
|
-
"""Compute the RMS of differences between FFT vectors of a1
|
|
34
|
-
|
|
57
|
+
"""Compute the RMS of differences between FFT vectors of a1 and projection of FFT vectors of a2.
|
|
58
|
+
|
|
35
59
|
This metric is sensitive to large scale changes and image noise but
|
|
36
60
|
insensitive to small rendering differences.
|
|
37
61
|
"""
|
|
38
|
-
|
|
39
62
|
ms = 0
|
|
40
|
-
|
|
41
63
|
for i in range(3):
|
|
42
64
|
fr1 = np.fft.fft2(a1[:, :, i])
|
|
43
65
|
fr2 = np.fft.fft2(a2[:, :, i])
|
|
@@ -49,579 +71,2054 @@ def fft_proj_rms(a1, a2):
|
|
|
49
71
|
p2 = np.arctan2(fr2.imag, fr2.real)
|
|
50
72
|
|
|
51
73
|
theta = p2 - p1
|
|
52
|
-
|
|
53
|
-
ms += ((
|
|
74
|
+
adjusted_ps2 = ps2 * np.cos(theta)
|
|
75
|
+
ms += ((adjusted_ps2 - ps1) ** 2).sum() / float(ps1.size)
|
|
54
76
|
|
|
55
77
|
rms = np.sqrt(ms)
|
|
56
78
|
|
|
57
79
|
return rms
|
|
58
80
|
|
|
59
81
|
|
|
60
|
-
def fft_metric(data1, data2, max_value=0.1):
|
|
61
|
-
"""Execute FFT metric
|
|
62
|
-
"""
|
|
63
|
-
|
|
82
|
+
def fft_metric(data1, data2, max_value=0.1, plot_failure=False):
|
|
83
|
+
"""Execute FFT metric."""
|
|
64
84
|
rms = fft_proj_rms(data1, data2)
|
|
65
|
-
|
|
85
|
+
within_threshold = rms <= max_value
|
|
86
|
+
if not within_threshold and plot_failure:
|
|
87
|
+
import matplotlib.pyplot as plt
|
|
66
88
|
|
|
89
|
+
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)
|
|
90
|
+
ax1.imshow(data1)
|
|
91
|
+
ax2.imshow(data2)
|
|
92
|
+
ax3.imshow(np.abs(data1.astype(np.float64) - data2.astype(np.float64)).astype(np.uint8))
|
|
93
|
+
plt.show()
|
|
94
|
+
return within_threshold
|
|
67
95
|
|
|
68
|
-
gshhs_root_dir = os.path.join(os.path.dirname(__file__), 'test_data', 'gshhs')
|
|
69
|
-
test_file = 'test_image.png'
|
|
70
|
-
grid_file = 'test_grid.png'
|
|
71
96
|
|
|
97
|
+
def europe():
|
|
98
|
+
"""Create a Europe area."""
|
|
99
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
100
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
101
|
+
area_def = (proj4_string, area_extent)
|
|
102
|
+
return area_def
|
|
72
103
|
|
|
73
|
-
class TestPycoast(unittest.TestCase):
|
|
74
104
|
|
|
75
|
-
|
|
76
|
-
img = Image.new('RGB', (640, 480))
|
|
77
|
-
img.save(test_file)
|
|
78
|
-
img.save(grid_file)
|
|
105
|
+
EUROPE = europe()
|
|
79
106
|
|
|
80
|
-
def tearDown(self):
|
|
81
|
-
os.remove(test_file)
|
|
82
|
-
os.remove(grid_file)
|
|
83
107
|
|
|
108
|
+
def geos():
|
|
109
|
+
"""Create a geos area."""
|
|
110
|
+
proj4_string = "+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0"
|
|
111
|
+
area_extent = (
|
|
112
|
+
-5570248.4773392612,
|
|
113
|
+
-5567248.074173444,
|
|
114
|
+
5567248.074173444,
|
|
115
|
+
5570248.4773392612,
|
|
116
|
+
)
|
|
117
|
+
area_def = (proj4_string, area_extent)
|
|
118
|
+
return area_def
|
|
84
119
|
|
|
85
|
-
class TestPIL(TestPycoast):
|
|
86
120
|
|
|
87
|
-
|
|
88
|
-
euro_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
89
|
-
'contours_europe.png'))
|
|
90
|
-
euro_data = np.array(euro_img)
|
|
121
|
+
GEOS = geos()
|
|
91
122
|
|
|
92
|
-
img = Image.new('RGB', (640, 480))
|
|
93
|
-
proj4_string = \
|
|
94
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
95
|
-
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
96
|
-
area_def = (proj4_string, area_extent)
|
|
97
|
-
cw = ContourWriter(gshhs_root_dir)
|
|
98
|
-
cw.add_coastlines(img, area_def, resolution='l', level=4)
|
|
99
|
-
cw.add_rivers(img, area_def, level=5, outline='blue')
|
|
100
|
-
cw.add_borders(img, area_def, outline=(255, 0, 0))
|
|
101
123
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
124
|
+
def germ():
|
|
125
|
+
"""Create an area covering Germany."""
|
|
126
|
+
proj4_string = "+proj=stere +ellps=bessel +lat_0=90.0 +lon_0=5.0 +lat_ts=50.0 +a=6378144.0 +b=6356759.0"
|
|
127
|
+
area_extent = [-155100.436345, -4441495.37946, 868899.563655, -3417495.37946]
|
|
128
|
+
area_def = (proj4_string, area_extent)
|
|
129
|
+
return area_def
|
|
105
130
|
|
|
106
|
-
def test_europe_file(self):
|
|
107
|
-
euro_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
108
|
-
'contours_europe.png'))
|
|
109
|
-
euro_data = np.array(euro_img)
|
|
110
131
|
|
|
111
|
-
|
|
112
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
113
|
-
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
114
|
-
area_def = (proj4_string, area_extent)
|
|
115
|
-
cw = ContourWriter(gshhs_root_dir)
|
|
116
|
-
cw.add_coastlines_to_file(test_file, area_def, resolution='l', level=4)
|
|
117
|
-
cw.add_rivers_to_file(test_file, area_def, level=5, outline='blue')
|
|
118
|
-
cw.add_borders_to_file(test_file, area_def, outline=(255, 0, 0))
|
|
132
|
+
GERM = germ()
|
|
119
133
|
|
|
120
|
-
img = Image.open(test_file)
|
|
121
|
-
res = np.array(img)
|
|
122
|
-
self.assertTrue(
|
|
123
|
-
fft_metric(euro_data, res), 'Writing of contours failed')
|
|
124
134
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
def dateline_1():
|
|
136
|
+
"""Create an area covering the dateline."""
|
|
137
|
+
proj4_string = "+proj=stere +lon_0=-170.00 +lat_0=60.00 +lat_ts=50.00 +ellps=WGS84"
|
|
138
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
139
|
+
area_def = (proj4_string, area_extent)
|
|
140
|
+
return area_def
|
|
129
141
|
|
|
130
|
-
img = Image.new('RGB', (425, 425))
|
|
131
|
-
proj4_string = \
|
|
132
|
-
'+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
|
|
133
|
-
area_extent = (-5570248.4773392612, -5567248.074173444,
|
|
134
|
-
5567248.074173444, 5570248.4773392612)
|
|
135
|
-
area_def = (proj4_string, area_extent)
|
|
136
|
-
cw = ContourWriter(gshhs_root_dir)
|
|
137
|
-
cw.add_coastlines(img, area_def, resolution='l')
|
|
138
142
|
|
|
139
|
-
|
|
140
|
-
self.assertTrue(
|
|
141
|
-
fft_metric(geos_data, res), 'Writing of geos contours failed')
|
|
143
|
+
DATELINE_1 = dateline_1()
|
|
142
144
|
|
|
143
|
-
def test_grid(self):
|
|
144
|
-
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
145
|
-
'grid_europe.png'))
|
|
146
|
-
grid_data = np.array(grid_img)
|
|
147
|
-
img = Image.new('RGB', (640, 480))
|
|
148
|
-
proj4_string = \
|
|
149
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
150
|
-
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
151
|
-
area_def = (proj4_string, area_extent)
|
|
152
145
|
|
|
153
|
-
|
|
146
|
+
def dateline_2():
|
|
147
|
+
"""Create another area covering the dateline."""
|
|
148
|
+
proj4_string = "+proj=stere +lon_0=140.00 +lat_0=60.00 +lat_ts=50.00 +ellps=WGS84"
|
|
149
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
150
|
+
area_def = (proj4_string, area_extent)
|
|
151
|
+
return area_def
|
|
154
152
|
|
|
155
|
-
cw.add_coastlines(img, area_def, resolution='l', level=4)
|
|
156
|
-
font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
|
|
157
|
-
'test_data', 'DejaVuSerif.ttf'),
|
|
158
|
-
16)
|
|
159
|
-
cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
|
|
160
|
-
font=font, fill='blue', write_text=False,
|
|
161
|
-
outline='blue', minor_outline='blue')
|
|
162
153
|
|
|
163
|
-
|
|
164
|
-
self.assertTrue(fft_metric(grid_data, res), 'Writing of grid failed')
|
|
154
|
+
DATELINE_2 = dateline_2()
|
|
165
155
|
|
|
166
|
-
def test_grid_geos(self):
|
|
167
|
-
geos_img = Image.open(
|
|
168
|
-
os.path.join(os.path.dirname(__file__), 'grid_geos.png'))
|
|
169
|
-
geos_data = np.array(geos_img)
|
|
170
|
-
img = Image.new('RGB', (425, 425))
|
|
171
|
-
proj4_string = \
|
|
172
|
-
'+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
|
|
173
|
-
area_extent = (-5570248.4773392612, -5567248.074173444,
|
|
174
|
-
5567248.074173444, 5570248.4773392612)
|
|
175
|
-
area_def = (proj4_string, area_extent)
|
|
176
|
-
cw = ContourWriter(gshhs_root_dir)
|
|
177
|
-
cw.add_coastlines(img, area_def, resolution='l')
|
|
178
|
-
cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), fill='blue',
|
|
179
|
-
outline='blue', minor_outline='blue',
|
|
180
|
-
write_text=False)
|
|
181
156
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
157
|
+
def lonlat_0(pm=0):
|
|
158
|
+
"""Create longlat projection over Cuba."""
|
|
159
|
+
proj4_string = "+proj=longlat +lon_0=0.0 +ellps=WGS84"
|
|
160
|
+
if pm:
|
|
161
|
+
proj4_string += f" +pm={pm}"
|
|
162
|
+
area_extent = (pm + -90.0, 15.0, pm + -70.0, 25.0)
|
|
163
|
+
area_def = (proj4_string, area_extent)
|
|
164
|
+
return area_def
|
|
185
165
|
|
|
186
|
-
def test_grid_file(self):
|
|
187
|
-
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
188
|
-
'grid_europe.png'))
|
|
189
|
-
grid_data = np.array(grid_img)
|
|
190
|
-
proj4_string = \
|
|
191
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
192
|
-
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
193
|
-
area_def = (proj4_string, area_extent)
|
|
194
166
|
|
|
195
|
-
|
|
167
|
+
LONLAT_0 = lonlat_0()
|
|
168
|
+
LONLAT_0_180 = lonlat_0(pm=180)
|
|
196
169
|
|
|
197
|
-
cw.add_coastlines_to_file(grid_file, area_def, resolution='l', level=4)
|
|
198
|
-
font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
|
|
199
|
-
'test_data', 'DejaVuSerif.ttf'),
|
|
200
|
-
16)
|
|
201
|
-
cw.add_grid_to_file(grid_file, area_def, (10.0, 10.0), (2.0, 2.0),
|
|
202
|
-
font=font, fill='blue', write_text=False,
|
|
203
|
-
outline='blue', minor_outline='blue')
|
|
204
170
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
171
|
+
def nh():
|
|
172
|
+
"""Create the nh area."""
|
|
173
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
174
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
175
|
+
area_def = (proj4_string, area_extent)
|
|
176
|
+
return area_def
|
|
208
177
|
|
|
209
|
-
def test_dateline_cross(self):
|
|
210
|
-
dl_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
211
|
-
'dateline_cross.png'))
|
|
212
|
-
dl_data = np.array(dl_img)
|
|
213
178
|
|
|
214
|
-
|
|
215
|
-
proj4_string = '+proj=stere +lon_0=-170.00 +lat_0=60.00 +lat_ts=50.00 +ellps=WGS84'
|
|
216
|
-
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
217
|
-
area_def = (proj4_string, area_extent)
|
|
179
|
+
NH = nh()
|
|
218
180
|
|
|
219
|
-
cw = ContourWriter(gshhs_root_dir)
|
|
220
181
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
outline='blue', minor_outline='blue',
|
|
228
|
-
lon_placement='b', lat_placement='lr')
|
|
182
|
+
def nh_1024():
|
|
183
|
+
"""Create the nh area in 1024x1024 pixels."""
|
|
184
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
185
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
186
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
187
|
+
return area_def
|
|
229
188
|
|
|
230
|
-
res = np.array(img)
|
|
231
|
-
self.assertTrue(fft_metric(dl_data, res),
|
|
232
|
-
'Writing of dateline crossing data failed')
|
|
233
189
|
|
|
234
|
-
|
|
235
|
-
dl_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
236
|
-
'dateline_boundary_cross.png'))
|
|
237
|
-
dl_data = np.array(dl_img)
|
|
190
|
+
NH_1024 = nh_1024()
|
|
238
191
|
|
|
239
|
-
img = Image.new('RGB', (640, 480))
|
|
240
|
-
proj4_string = \
|
|
241
|
-
'+proj=stere +lon_0=140.00 +lat_0=60.00 +lat_ts=50.00 +ellps=WGS84'
|
|
242
|
-
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
243
|
-
area_def = (proj4_string, area_extent)
|
|
244
192
|
|
|
245
|
-
|
|
193
|
+
def nh_def(shape):
|
|
194
|
+
"""Create the nh area definition with custom shape."""
|
|
195
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
196
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 0.0)
|
|
197
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, shape[1], shape[0], area_extent)
|
|
198
|
+
return area_def
|
|
246
199
|
|
|
247
|
-
cw.add_coastlines(img, area_def, resolution='l', level=4)
|
|
248
|
-
font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
|
|
249
|
-
'test_data',
|
|
250
|
-
'DejaVuSerif.ttf'), 16)
|
|
251
|
-
cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
|
|
252
|
-
font=font, fill='blue',
|
|
253
|
-
outline='blue', minor_outline='blue', write_text=False,
|
|
254
|
-
lon_placement='b', lat_placement='lr')
|
|
255
200
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
201
|
+
def brazil():
|
|
202
|
+
"""Create a Brazil area."""
|
|
203
|
+
proj4_string = "+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m"
|
|
204
|
+
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
|
|
205
|
+
area_def = (proj4_string, area_extent)
|
|
206
|
+
return area_def
|
|
259
207
|
|
|
260
|
-
def test_grid_nh(self):
|
|
261
|
-
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
262
|
-
'grid_nh.png'))
|
|
263
|
-
grid_data = np.array(grid_img)
|
|
264
|
-
img = Image.new('RGB', (425, 425))
|
|
265
|
-
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
|
|
266
|
-
area_extent = (-5326849.0625, -5326849.0625,
|
|
267
|
-
5326849.0625, 5326849.0625)
|
|
268
|
-
area_def = (proj4_string, area_extent)
|
|
269
208
|
|
|
270
|
-
|
|
209
|
+
BRAZIL = brazil()
|
|
271
210
|
|
|
272
|
-
cw.add_coastlines(img, area_def, resolution='l', level=4)
|
|
273
|
-
font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
|
|
274
|
-
'test_data', 'DejaVuSerif.ttf'),
|
|
275
|
-
10)
|
|
276
|
-
cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
|
|
277
|
-
font=font, fill='blue',
|
|
278
|
-
outline='blue', minor_outline='blue', write_text=False,
|
|
279
|
-
lon_placement='tblr', lat_placement='')
|
|
280
211
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
212
|
+
def nh_425():
|
|
213
|
+
"""Create the nh area in 425 pixels size."""
|
|
214
|
+
proj_dict = {
|
|
215
|
+
"proj": "laea",
|
|
216
|
+
"lat_0": 90.0,
|
|
217
|
+
"lon_0": 0.0,
|
|
218
|
+
"a": 6371228.0,
|
|
219
|
+
"units": "m",
|
|
220
|
+
}
|
|
221
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
222
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj_dict, 425, 425, area_extent)
|
|
223
|
+
return area_def
|
|
284
224
|
|
|
285
|
-
def test_add_polygon(self):
|
|
286
|
-
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
287
|
-
'nh_polygons.png'))
|
|
288
|
-
grid_data = np.array(grid_img)
|
|
289
|
-
img = Image.new('RGB', (425, 425))
|
|
290
|
-
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
|
|
291
|
-
area_extent = (-5326849.0625, -5326849.0625,
|
|
292
|
-
5326849.0625, 5326849.0625)
|
|
293
|
-
area_def = (proj4_string, area_extent)
|
|
294
225
|
|
|
295
|
-
|
|
226
|
+
NH_425 = nh_425()
|
|
296
227
|
|
|
297
|
-
polygons = {
|
|
298
|
-
'REYKJAVIK_ATC_A': ((-20.0, 73.0), (0.0, 73.0), (0.0, 61.0),
|
|
299
|
-
(-30.0, 61.0), (-39.0, 63.5), (-20, 70)),
|
|
300
|
-
'REYKJAVIK_ATC_B': (
|
|
301
|
-
(-39, 63.5), (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65),
|
|
302
|
-
(-76, 76), (-75, 78), (-60, 82), (0, 90),
|
|
303
|
-
(30, 82), (0, 82), (0, 73), (-20, 73), (-20, 70)),
|
|
304
|
-
'REYKJAVIK_ATC': (
|
|
305
|
-
(0.0, 73.0), (0.0, 61.0), (-30.0, 61.0), (-39, 63.5),
|
|
306
|
-
(-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65),
|
|
307
|
-
(-76, 76), (-75, 78), (-60, 82), (0, 90), (30, 82), (0, 82)),
|
|
308
|
-
'ICELAND_BOX': ((-25, 62.5), (-25, 67), (-13, 67), (-13, 62.5))
|
|
309
|
-
}
|
|
310
228
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
229
|
+
def eurasia():
|
|
230
|
+
"""Create a Eurasia area."""
|
|
231
|
+
proj4_string = "+proj=tmerc +ellps=WGS84 +lat_0=20.0 +lon_0=-50.0"
|
|
232
|
+
area_extent = [-4865942.5, 1781111.9, 4865942.5, 7235767.2]
|
|
233
|
+
area_def = (proj4_string, area_extent)
|
|
234
|
+
return area_def
|
|
315
235
|
|
|
316
|
-
res = np.array(img)
|
|
317
|
-
self.assertTrue(fft_metric(grid_data, res),
|
|
318
|
-
'Writing of nh polygons failed')
|
|
319
236
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
237
|
+
def north_atlantic():
|
|
238
|
+
"""Create a North Atlantic area."""
|
|
239
|
+
proj4_string = "+proj=tmerc +ellps=WGS84 +lat_0=20.0 +lon_0=50.0"
|
|
240
|
+
area_extent = [-4865942.5, 1781111.9, 4865942.5, 7235767.2]
|
|
241
|
+
area_def = (proj4_string, area_extent)
|
|
242
|
+
return area_def
|
|
324
243
|
|
|
325
|
-
img = Image.new('RGB', (425, 425))
|
|
326
|
-
proj4_string = '+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m'
|
|
327
|
-
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
|
|
328
|
-
area_def = (proj4_string, area_extent)
|
|
329
244
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
'test_data/shapes/Metareas.shp'),
|
|
337
|
-
outline='red')
|
|
338
|
-
cw.add_shapefile_shape(img, area_def,
|
|
339
|
-
os.path.join(os.path.dirname(__file__),
|
|
340
|
-
'test_data/shapes/divisao_politica/BR_Regioes.shp'), 3,
|
|
341
|
-
outline='blue')
|
|
342
|
-
cw.add_shapefile_shape(img, area_def,
|
|
343
|
-
os.path.join(os.path.dirname(__file__),
|
|
344
|
-
'test_data/shapes/divisao_politica/BR_Regioes.shp'), 4,
|
|
345
|
-
outline='blue', fill='green')
|
|
245
|
+
def uk_and_ireland():
|
|
246
|
+
"""Create an area covering Ireland and the UK."""
|
|
247
|
+
proj4_string = "+proj=stere +ellps=WGS84 +lon_0=-4.532 +lat_0=54.228"
|
|
248
|
+
area_extent = (-600000.0, -600000.0, 600000.0, 600000.0)
|
|
249
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 800, 800, area_extent)
|
|
250
|
+
return area_def
|
|
346
251
|
|
|
347
|
-
res = np.array(img)
|
|
348
|
-
self.assertTrue(
|
|
349
|
-
fft_metric(grid_data, res), 'Writing of Brazil shapefiles failed')
|
|
350
252
|
|
|
253
|
+
def south_america():
|
|
254
|
+
"""Create an area covering south America."""
|
|
255
|
+
proj4_string = "+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m"
|
|
256
|
+
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
|
|
257
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 425, 425, area_extent)
|
|
258
|
+
return area_def
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def europe_1024():
|
|
262
|
+
"""Create a Europe area in 1024 pixels size."""
|
|
263
|
+
proj4_string = "+proj=stere +ellps=WGS84 +lat_0=51.5 +lon_0=-0.1"
|
|
264
|
+
area_extent = (-2000000.0, -2000000.0, 2000000.0, 2000000.0)
|
|
265
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
266
|
+
return area_def
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def bering_straight():
|
|
270
|
+
"""Create an area covering the Bering straight."""
|
|
271
|
+
proj4_string = "+proj=merc +ellps=WGS84 +lon_0=170.0"
|
|
272
|
+
area_extent = [-3899875.0, 1795000.0, 5014125.0, 9600000.0]
|
|
273
|
+
area_def = (proj4_string, area_extent)
|
|
274
|
+
return area_def
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def hawaii():
|
|
278
|
+
"""Create an area covering Hawai."""
|
|
279
|
+
proj4_string = "+proj=tmerc +ellps=WGS84 +lon_0=-155.0"
|
|
280
|
+
area_extent = [-3503550.0, -556597.5, 3503550.0, 5009377.3]
|
|
281
|
+
area_def = (proj4_string, area_extent)
|
|
282
|
+
return area_def
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@pytest.fixture(scope="session")
|
|
286
|
+
def cw_pil():
|
|
287
|
+
"""Create a PIL ContourWriter."""
|
|
288
|
+
from pycoast import ContourWriterPIL
|
|
289
|
+
|
|
290
|
+
cw = ContourWriterPIL(gshhs_root_dir)
|
|
291
|
+
return cw
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@pytest.fixture
|
|
295
|
+
def cw_agg():
|
|
296
|
+
"""Create a PIL ContourWriter."""
|
|
297
|
+
from pycoast import ContourWriterAGG
|
|
298
|
+
|
|
299
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
300
|
+
return cw
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@pytest.fixture
|
|
304
|
+
def new_test_image(request, tmp_path):
|
|
305
|
+
"""Create a new test image, and save it to tmp_path if the test fails."""
|
|
306
|
+
img_container = []
|
|
307
|
+
|
|
308
|
+
def _new_test_image(mode, shape, filename, color=0):
|
|
309
|
+
img = Image.new(mode, shape, color=color)
|
|
310
|
+
img_container.append(filename)
|
|
311
|
+
img_container.append(img)
|
|
312
|
+
return img
|
|
313
|
+
|
|
314
|
+
yield _new_test_image
|
|
315
|
+
try:
|
|
316
|
+
filename, img = img_container
|
|
317
|
+
except ValueError: # the fixture wasn't used
|
|
318
|
+
return
|
|
319
|
+
if request.node.rep_call.failed:
|
|
320
|
+
failed_path = tmp_path / filename
|
|
321
|
+
print(f"Failed image saved to: {failed_path}")
|
|
322
|
+
img.save(failed_path)
|
|
351
323
|
|
|
352
|
-
|
|
353
|
-
|
|
324
|
+
|
|
325
|
+
def images_match(ref_image, test_image):
|
|
326
|
+
"""Check is images match."""
|
|
327
|
+
return fft_metric(np.array(ref_image), np.array(test_image))
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
class _ContourWriterTestBase:
|
|
331
|
+
"""Base class for test classes that need example images."""
|
|
332
|
+
|
|
333
|
+
def setup_method(self):
|
|
334
|
+
img = Image.new("RGB", (640, 480))
|
|
335
|
+
img.save(test_filename)
|
|
336
|
+
img.save(grid_filename)
|
|
337
|
+
img_p = Image.new("P", (640, 480))
|
|
338
|
+
img_p.save(p_coasts_filename)
|
|
339
|
+
|
|
340
|
+
def teardown_method(self):
|
|
341
|
+
os.remove(test_filename)
|
|
342
|
+
os.remove(grid_filename)
|
|
343
|
+
os.remove(p_coasts_filename)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@pytest.fixture
|
|
347
|
+
def test_file_path(tmp_path):
|
|
348
|
+
"""Create a test image file on disk."""
|
|
349
|
+
path = tmp_path / test_filename
|
|
350
|
+
img = Image.new("RGB", (640, 480))
|
|
351
|
+
img.save(path)
|
|
352
|
+
yield path
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@pytest.fixture
|
|
356
|
+
def grid_file_path(tmp_path):
|
|
357
|
+
"""Create a test grid image file on disk."""
|
|
358
|
+
path = tmp_path / grid_filename
|
|
359
|
+
img = Image.new("RGB", (640, 480))
|
|
360
|
+
img.save(path)
|
|
361
|
+
yield path
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
class TestContourWriterPIL:
|
|
365
|
+
"""Test PIL-based contour writer."""
|
|
366
|
+
|
|
367
|
+
def test_europe_coastlines_rivers_and_borders(self, cw_pil, new_test_image):
|
|
368
|
+
"""Test coastlines, rivers and borders over Europe."""
|
|
369
|
+
filename = "contours_europe.png"
|
|
370
|
+
|
|
371
|
+
euro_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
372
|
+
|
|
373
|
+
img = new_test_image("RGB", (640, 480), filename)
|
|
374
|
+
|
|
375
|
+
area_def = EUROPE
|
|
376
|
+
cw_pil.add_coastlines(img, area_def, resolution="l", level=4)
|
|
377
|
+
cw_pil.add_rivers(img, area_def, level=5, outline="blue")
|
|
378
|
+
cw_pil.add_borders(img, area_def, outline=(255, 0, 0), level=1)
|
|
379
|
+
|
|
380
|
+
assert images_match(euro_img, img), "Writing of contours failed"
|
|
381
|
+
|
|
382
|
+
def test_europe_coastlines_rivers_and_borders_on_file(self, cw_pil, test_file_path):
|
|
383
|
+
"""Test coastlines, rivers and borders over Europe on a file."""
|
|
384
|
+
filename = "contours_europe.png"
|
|
385
|
+
euro_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
386
|
+
|
|
387
|
+
area_def = EUROPE
|
|
388
|
+
cw_pil.add_coastlines_to_file(test_file_path, area_def, resolution="l", level=4)
|
|
389
|
+
cw_pil.add_rivers_to_file(test_file_path, area_def, level=5, outline="blue")
|
|
390
|
+
cw_pil.add_borders_to_file(test_file_path, area_def, outline=(255, 0, 0))
|
|
391
|
+
|
|
392
|
+
img = Image.open(test_file_path)
|
|
393
|
+
assert images_match(euro_img, img), "Writing of contours to file failed"
|
|
394
|
+
|
|
395
|
+
def test_geos(self, cw_pil, new_test_image):
|
|
396
|
+
filename = "contours_geos.png"
|
|
397
|
+
geos_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
398
|
+
|
|
399
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
400
|
+
area_def = GEOS
|
|
401
|
+
cw_pil.add_coastlines(img, area_def, resolution="l")
|
|
402
|
+
|
|
403
|
+
assert images_match(geos_img, img), "Writing of geos contours failed"
|
|
404
|
+
|
|
405
|
+
@pytest.mark.parametrize(
|
|
406
|
+
"filename, shape, area_def, level, grid_kwargs",
|
|
407
|
+
[
|
|
408
|
+
(
|
|
409
|
+
"grid_europe.png",
|
|
410
|
+
(640, 480),
|
|
411
|
+
EUROPE,
|
|
412
|
+
4,
|
|
413
|
+
dict(fill="blue", write_text=False, outline="blue", minor_outline="blue"),
|
|
414
|
+
),
|
|
415
|
+
(
|
|
416
|
+
"grid_geos.png",
|
|
417
|
+
(425, 425),
|
|
418
|
+
GEOS,
|
|
419
|
+
1,
|
|
420
|
+
dict(fill="blue", write_text=False, outline="blue", minor_outline="blue"),
|
|
421
|
+
),
|
|
422
|
+
(
|
|
423
|
+
"grid_geos.png",
|
|
424
|
+
(425, 425),
|
|
425
|
+
GEOS,
|
|
426
|
+
1,
|
|
427
|
+
dict(fill="blue", write_text=True, outline="blue", minor_outline="blue"),
|
|
428
|
+
),
|
|
429
|
+
(
|
|
430
|
+
"grid_germ.png",
|
|
431
|
+
(1024, 1024),
|
|
432
|
+
GERM,
|
|
433
|
+
4,
|
|
434
|
+
dict(fill="yellow", write_text=True, outline="red", minor_outline="white"),
|
|
435
|
+
),
|
|
436
|
+
(
|
|
437
|
+
"dateline_cross.png",
|
|
438
|
+
(640, 480),
|
|
439
|
+
DATELINE_1,
|
|
440
|
+
4,
|
|
441
|
+
dict(
|
|
442
|
+
fill="blue",
|
|
443
|
+
write_text=False,
|
|
444
|
+
outline="blue",
|
|
445
|
+
minor_outline="blue",
|
|
446
|
+
lon_placement="b",
|
|
447
|
+
lat_placement="lr",
|
|
448
|
+
),
|
|
449
|
+
),
|
|
450
|
+
(
|
|
451
|
+
"dateline_boundary_cross.png",
|
|
452
|
+
(640, 480),
|
|
453
|
+
DATELINE_2,
|
|
454
|
+
4,
|
|
455
|
+
dict(
|
|
456
|
+
fill="blue",
|
|
457
|
+
write_text=False,
|
|
458
|
+
outline="blue",
|
|
459
|
+
minor_outline="blue",
|
|
460
|
+
lon_placement="b",
|
|
461
|
+
lat_placement="lr",
|
|
462
|
+
),
|
|
463
|
+
),
|
|
464
|
+
(
|
|
465
|
+
"lonlat_boundary_cross.png",
|
|
466
|
+
(640, 480),
|
|
467
|
+
LONLAT_0,
|
|
468
|
+
4,
|
|
469
|
+
dict(
|
|
470
|
+
fill="blue",
|
|
471
|
+
write_text=False,
|
|
472
|
+
outline="blue",
|
|
473
|
+
minor_outline="blue",
|
|
474
|
+
lon_placement="b",
|
|
475
|
+
lat_placement="lr",
|
|
476
|
+
),
|
|
477
|
+
),
|
|
478
|
+
(
|
|
479
|
+
"lonlat_boundary_cross.png",
|
|
480
|
+
(640, 480),
|
|
481
|
+
LONLAT_0_180,
|
|
482
|
+
4,
|
|
483
|
+
dict(
|
|
484
|
+
fill="blue",
|
|
485
|
+
write_text=False,
|
|
486
|
+
outline="blue",
|
|
487
|
+
minor_outline="blue",
|
|
488
|
+
lon_placement="b",
|
|
489
|
+
lat_placement="lr",
|
|
490
|
+
),
|
|
491
|
+
),
|
|
492
|
+
],
|
|
493
|
+
)
|
|
494
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
495
|
+
def test_grid(self, cw_pil, new_test_image, filename, shape, area_def, level, grid_kwargs):
|
|
496
|
+
img = new_test_image("RGB", shape, filename)
|
|
497
|
+
|
|
498
|
+
cw_pil.add_coastlines(img, area_def, resolution="l", level=level)
|
|
499
|
+
font = pil_font_16
|
|
500
|
+
cw_pil.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font, **grid_kwargs)
|
|
501
|
+
|
|
502
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
503
|
+
assert images_match(grid_img, img), "Writing of grid failed"
|
|
504
|
+
|
|
505
|
+
def test_grid_nh(self, cw_pil, new_test_image):
|
|
506
|
+
filename = "grid_nh.png"
|
|
507
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
508
|
+
|
|
509
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
510
|
+
area_def = NH
|
|
511
|
+
|
|
512
|
+
cw_pil.add_coastlines(img, area_def, resolution="l", level=4)
|
|
513
|
+
font = ImageFont.truetype(font_path, 10)
|
|
514
|
+
cw_pil.add_grid(
|
|
515
|
+
img,
|
|
516
|
+
area_def,
|
|
517
|
+
(10.0, 10.0),
|
|
518
|
+
(2.0, 2.0),
|
|
519
|
+
font=font,
|
|
520
|
+
fill="blue",
|
|
521
|
+
outline="blue",
|
|
522
|
+
minor_outline="blue",
|
|
523
|
+
write_text=False,
|
|
524
|
+
lon_placement="tblr",
|
|
525
|
+
lat_placement="",
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
assert images_match(grid_img, img), "Writing of nh grid failed"
|
|
529
|
+
|
|
530
|
+
def test_grid_file(self, cw_pil, grid_file_path):
|
|
531
|
+
filename = "grid_europe.png"
|
|
532
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
533
|
+
|
|
534
|
+
area_def = EUROPE
|
|
535
|
+
|
|
536
|
+
cw_pil.add_coastlines_to_file(grid_file_path, area_def, resolution="l", level=4)
|
|
537
|
+
font = pil_font_16
|
|
538
|
+
cw_pil.add_grid_to_file(
|
|
539
|
+
grid_file_path,
|
|
540
|
+
area_def,
|
|
541
|
+
(10.0, 10.0),
|
|
542
|
+
(2.0, 2.0),
|
|
543
|
+
font=font,
|
|
544
|
+
fill="blue",
|
|
545
|
+
write_text=False,
|
|
546
|
+
outline="blue",
|
|
547
|
+
minor_outline="blue",
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
img = Image.open(grid_file_path)
|
|
551
|
+
assert images_match(grid_img, img), "Writing of grid failed"
|
|
552
|
+
|
|
553
|
+
def test_add_polygon(self, cw_pil, new_test_image):
|
|
554
|
+
filename = "nh_polygons.png"
|
|
555
|
+
ref_image = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
556
|
+
|
|
557
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
558
|
+
area_def = NH
|
|
559
|
+
|
|
560
|
+
polygons = {
|
|
561
|
+
"REYKJAVIK_ATC_A": (
|
|
562
|
+
(-20.0, 73.0),
|
|
563
|
+
(0.0, 73.0),
|
|
564
|
+
(0.0, 61.0),
|
|
565
|
+
(-30.0, 61.0),
|
|
566
|
+
(-39.0, 63.5),
|
|
567
|
+
(-20, 70),
|
|
568
|
+
),
|
|
569
|
+
"REYKJAVIK_ATC_B": (
|
|
570
|
+
(-39, 63.5),
|
|
571
|
+
(-55 + 4 / 6.0, 63.5),
|
|
572
|
+
(-57 + 45 / 60.0, 65),
|
|
573
|
+
(-76, 76),
|
|
574
|
+
(-75, 78),
|
|
575
|
+
(-60, 82),
|
|
576
|
+
(0, 90),
|
|
577
|
+
(30, 82),
|
|
578
|
+
(0, 82),
|
|
579
|
+
(0, 73),
|
|
580
|
+
(-20, 73),
|
|
581
|
+
(-20, 70),
|
|
582
|
+
),
|
|
583
|
+
"REYKJAVIK_ATC": (
|
|
584
|
+
(0.0, 73.0),
|
|
585
|
+
(0.0, 61.0),
|
|
586
|
+
(-30.0, 61.0),
|
|
587
|
+
(-39, 63.5),
|
|
588
|
+
(-55 + 4 / 6.0, 63.5),
|
|
589
|
+
(-57 + 45 / 60.0, 65),
|
|
590
|
+
(-76, 76),
|
|
591
|
+
(-75, 78),
|
|
592
|
+
(-60, 82),
|
|
593
|
+
(0, 90),
|
|
594
|
+
(30, 82),
|
|
595
|
+
(0, 82),
|
|
596
|
+
),
|
|
597
|
+
"ICELAND_BOX": ((-25, 62.5), (-25, 67), (-13, 67), (-13, 62.5)),
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
cw_pil.add_polygon(img, area_def, polygons["REYKJAVIK_ATC"], outline="red")
|
|
601
|
+
cw_pil.add_polygon(img, area_def, polygons["ICELAND_BOX"], outline="green", fill="gray")
|
|
602
|
+
cw_pil.add_coastlines(img, area_def, resolution="l", level=4)
|
|
603
|
+
|
|
604
|
+
assert images_match(ref_image, img), "Writing of nh polygons failed"
|
|
605
|
+
|
|
606
|
+
def test_add_points_pil(self, cw_pil, new_test_image):
|
|
607
|
+
filename = "nh_points_pil.png"
|
|
608
|
+
ref_image = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
609
|
+
|
|
610
|
+
img = new_test_image("RGB", (1024, 1024), filename, color=(255, 255, 255))
|
|
611
|
+
|
|
612
|
+
area_def = NH_1024
|
|
613
|
+
|
|
614
|
+
cw_pil.add_coastlines(img, area_def, outline="black", resolution="l", level=4)
|
|
615
|
+
cw_pil.add_borders(img, area_def, outline="black", level=1, resolution="c")
|
|
616
|
+
|
|
617
|
+
points_list = [((13.4050, 52.5200), "Berlin")]
|
|
618
|
+
cw_pil.add_points(
|
|
619
|
+
img,
|
|
620
|
+
area_def,
|
|
621
|
+
points_list=points_list,
|
|
622
|
+
font_file=font_path,
|
|
623
|
+
symbol="asterisk",
|
|
624
|
+
ptsize=6,
|
|
625
|
+
outline="red",
|
|
626
|
+
box_outline="black",
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
points_list = [((12.4964, 41.9028), "Rome")]
|
|
630
|
+
cw_pil.add_points(
|
|
631
|
+
img,
|
|
632
|
+
area_def,
|
|
633
|
+
points_list=points_list,
|
|
634
|
+
font_file=font_path,
|
|
635
|
+
symbol="square",
|
|
636
|
+
ptsize=6,
|
|
637
|
+
outline="blue",
|
|
638
|
+
fill="yellow",
|
|
639
|
+
box_outline="black",
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
assert images_match(ref_image, img), "Writing of nh points failed"
|
|
643
|
+
|
|
644
|
+
def test_add_points_coordinate_conversion(self, cw_pil, new_test_image):
|
|
645
|
+
"""Check that a point added with lonlat coordinates matches the same point in pixel coordinates."""
|
|
646
|
+
shape = (512, 1024)
|
|
647
|
+
area_def = nh_def(shape)
|
|
648
|
+
lonlat_coords = (13.4050, 52.5200)
|
|
649
|
+
pixel_colrow = area_def.get_array_indices_from_lonlat(*lonlat_coords)
|
|
650
|
+
negative_pixel_colrow = (pixel_colrow[0] - shape[1], pixel_colrow[1] - shape[0])
|
|
651
|
+
|
|
652
|
+
img1 = Image.new("RGB", shape[::-1], (255, 255, 255))
|
|
653
|
+
|
|
654
|
+
points_list = [(lonlat_coords, "Berlin")]
|
|
655
|
+
cw_pil.add_points(
|
|
656
|
+
img1,
|
|
657
|
+
area_def,
|
|
658
|
+
points_list=points_list,
|
|
659
|
+
font_file=font_path,
|
|
660
|
+
symbol="asterisk",
|
|
661
|
+
ptsize=6,
|
|
662
|
+
outline="red",
|
|
663
|
+
)
|
|
664
|
+
res1 = np.array(img1)
|
|
665
|
+
assert (res1[..., 0] == 255).all() # everything is either white or red
|
|
666
|
+
assert (res1[..., 1] != 255).any() # not a completely white/empty image
|
|
667
|
+
assert (res1[..., 2] != 255).any() # not a completely white/empty image
|
|
668
|
+
|
|
669
|
+
for img_coords in (pixel_colrow, negative_pixel_colrow):
|
|
670
|
+
img2 = Image.new("RGB", shape[::-1], (255, 255, 255))
|
|
671
|
+
points_list = [(img_coords, "Berlin")]
|
|
672
|
+
cw_pil.add_points(
|
|
673
|
+
img2,
|
|
674
|
+
area_def,
|
|
675
|
+
points_list=points_list,
|
|
676
|
+
font_file=font_path,
|
|
677
|
+
symbol="asterisk",
|
|
678
|
+
ptsize=6,
|
|
679
|
+
outline="red",
|
|
680
|
+
coord_ref="image",
|
|
681
|
+
)
|
|
682
|
+
res2 = np.array(img2)
|
|
683
|
+
assert (res2 != 255).any() # not a completely black/empty image
|
|
684
|
+
np.testing.assert_allclose(res1, res2)
|
|
685
|
+
|
|
686
|
+
def test_add_points_bad_image_coords(self, cw_pil):
|
|
687
|
+
shape = (512, 1024)
|
|
688
|
+
area_def = nh_def(shape)
|
|
689
|
+
for pixel_colrow in (shape[::-1], (-10000, -10000)):
|
|
690
|
+
img1 = Image.new("RGB", shape[::-1], (255, 255, 255))
|
|
691
|
+
|
|
692
|
+
points_list = [(pixel_colrow, "Berlin")]
|
|
693
|
+
cw_pil.add_points(
|
|
694
|
+
img1,
|
|
695
|
+
area_def,
|
|
696
|
+
points_list=points_list,
|
|
697
|
+
font_file=font_path,
|
|
698
|
+
symbol="asterisk",
|
|
699
|
+
ptsize=6,
|
|
700
|
+
outline="red",
|
|
701
|
+
coord_ref="image",
|
|
702
|
+
)
|
|
703
|
+
res1 = np.array(img1)
|
|
704
|
+
np.testing.assert_allclose(res1, 255) # no added points
|
|
705
|
+
|
|
706
|
+
def test_add_points_bad_coord_ref(self, cw_pil):
|
|
707
|
+
shape = (512, 1024)
|
|
708
|
+
area_def = nh_def(shape)
|
|
709
|
+
img1 = Image.new("RGB", shape[::-1], (255, 255, 255))
|
|
710
|
+
points_list = [((0, 0), "Berlin")]
|
|
711
|
+
with pytest.raises(ValueError):
|
|
712
|
+
cw_pil.add_points(
|
|
713
|
+
img1,
|
|
714
|
+
area_def,
|
|
715
|
+
points_list=points_list,
|
|
716
|
+
font_file=font_path,
|
|
717
|
+
symbol="asterisk",
|
|
718
|
+
ptsize=6,
|
|
719
|
+
outline="red",
|
|
720
|
+
coord_ref="fake",
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
def test_add_shapefile_shapes(self, cw_pil, new_test_image):
|
|
724
|
+
filename = "brazil_shapefiles.png"
|
|
725
|
+
ref_image = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
726
|
+
|
|
727
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
728
|
+
area_def = BRAZIL
|
|
729
|
+
|
|
730
|
+
cw_pil.add_coastlines(img, area_def, resolution="l", level=4)
|
|
731
|
+
cw_pil.add_shapefile_shapes(
|
|
732
|
+
img,
|
|
733
|
+
area_def,
|
|
734
|
+
os.path.join(LOCAL_DIR, "test_data/shapes/Metareas.shp"),
|
|
735
|
+
outline="red",
|
|
736
|
+
)
|
|
737
|
+
cw_pil.add_shapefile_shape(
|
|
738
|
+
img,
|
|
739
|
+
area_def,
|
|
740
|
+
os.path.join(
|
|
741
|
+
LOCAL_DIR,
|
|
742
|
+
"test_data/shapes/divisao_politica/BR_Regioes.shp",
|
|
743
|
+
),
|
|
744
|
+
3,
|
|
745
|
+
outline="blue",
|
|
746
|
+
)
|
|
747
|
+
cw_pil.add_shapefile_shape(
|
|
748
|
+
img,
|
|
749
|
+
area_def,
|
|
750
|
+
os.path.join(
|
|
751
|
+
LOCAL_DIR,
|
|
752
|
+
"test_data/shapes/divisao_politica/BR_Regioes.shp",
|
|
753
|
+
),
|
|
754
|
+
4,
|
|
755
|
+
outline="blue",
|
|
756
|
+
fill="green",
|
|
757
|
+
)
|
|
758
|
+
|
|
759
|
+
assert images_match(ref_image, img), "Writing of Brazil shapefiles failed"
|
|
760
|
+
|
|
761
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
762
|
+
def test_config_file_coasts_and_grid(self, cw_pil, new_test_image):
|
|
763
|
+
overlay_config = os.path.join(LOCAL_DIR, "coasts_and_grid.ini")
|
|
764
|
+
filename = "grid_nh.png"
|
|
765
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
766
|
+
|
|
767
|
+
area_def = NH_425
|
|
768
|
+
|
|
769
|
+
overlay = cw_pil.add_overlay_from_config(overlay_config, area_def)
|
|
770
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
771
|
+
img.paste(overlay, mask=overlay)
|
|
772
|
+
assert images_match(grid_img, img), "Writing of nh grid failed"
|
|
773
|
+
|
|
774
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
775
|
+
def test_config_file_points_and_borders_pil(self, cw_pil, new_test_image):
|
|
776
|
+
config_file = os.path.join(LOCAL_DIR, "nh_points_pil.ini")
|
|
777
|
+
filename = "nh_points_cfg_pil.png"
|
|
778
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
779
|
+
|
|
780
|
+
img = new_test_image("RGB", (1024, 1024), filename, color=(255, 255, 255))
|
|
781
|
+
|
|
782
|
+
area_def = NH_1024
|
|
783
|
+
|
|
784
|
+
cw_pil.add_overlay_from_config(config_file, area_def, img)
|
|
785
|
+
|
|
786
|
+
assert images_match(grid_img, img), "Writing of nh points failed"
|
|
787
|
+
|
|
788
|
+
def test_add_cities_pil(self, cw_pil, new_test_image):
|
|
789
|
+
filename = "nh_cities_pil.png"
|
|
790
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
791
|
+
|
|
792
|
+
img = new_test_image("RGB", (1024, 1024), filename, color=(255, 255, 255))
|
|
793
|
+
|
|
794
|
+
area_def = NH_1024
|
|
795
|
+
|
|
796
|
+
cw_pil.add_coastlines(img, area_def, outline="black", resolution="l", level=4)
|
|
797
|
+
cw_pil.add_borders(img, area_def, outline="black", level=1, resolution="c")
|
|
798
|
+
|
|
799
|
+
cities_list = ["Zurich", "Oslo", "Reykjavik", "Fairbanks", "Toronto"]
|
|
800
|
+
cw_pil.add_cities(
|
|
801
|
+
img,
|
|
802
|
+
area_def,
|
|
803
|
+
cities_list=cities_list,
|
|
804
|
+
font_file=font_path,
|
|
805
|
+
font_size=20,
|
|
806
|
+
symbol="square",
|
|
807
|
+
ptsize=16,
|
|
808
|
+
outline="black",
|
|
809
|
+
width=3,
|
|
810
|
+
fill="blue",
|
|
811
|
+
fill_opacity=128,
|
|
812
|
+
box_outline="blue",
|
|
813
|
+
box_linewidth=0.5,
|
|
814
|
+
box_fill="yellow",
|
|
815
|
+
box_opacity=200,
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
assert images_match(grid_img, img), "Writing of nh cities_pil failed"
|
|
819
|
+
|
|
820
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
821
|
+
def test_add_cities_cfg_pil(self, cw_pil, new_test_image):
|
|
822
|
+
config_file = os.path.join(LOCAL_DIR, "nh_cities_pil.ini")
|
|
823
|
+
filename = "nh_cities_pil.png"
|
|
824
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
825
|
+
|
|
826
|
+
img = new_test_image("RGB", (1024, 1024), filename, color=(255, 255, 255))
|
|
827
|
+
|
|
828
|
+
area_def = NH_1024
|
|
829
|
+
|
|
830
|
+
cw_pil.add_overlay_from_config(config_file, area_def, img)
|
|
831
|
+
|
|
832
|
+
assert images_match(grid_img, img), "Writing of nh cities_cfg_pil failed"
|
|
833
|
+
|
|
834
|
+
def test_add_cities_from_dict_pil(self, cw_pil, new_test_image):
|
|
835
|
+
filename = "nh_cities_from_dict_pil.png"
|
|
836
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
837
|
+
|
|
838
|
+
img = new_test_image("RGB", (1024, 1024), filename, color=(255, 255, 255))
|
|
839
|
+
|
|
840
|
+
area_def = europe_1024()
|
|
841
|
+
|
|
842
|
+
overlays = {}
|
|
843
|
+
overlays["coasts"] = {"level": 4, "resolution": "l", "outline": "black"}
|
|
844
|
+
overlays["borders"] = {"level": 1, "outline": "black", "resolution": "c"}
|
|
845
|
+
cities_list1 = [
|
|
846
|
+
"Berlin",
|
|
847
|
+
"Paris",
|
|
848
|
+
"London",
|
|
849
|
+
"Dublin",
|
|
850
|
+
"Madrid",
|
|
851
|
+
"Reykjavik",
|
|
852
|
+
"Oslo",
|
|
853
|
+
"Rome",
|
|
854
|
+
]
|
|
855
|
+
cities_list2 = ["Freiburg", "Montelimar", "Huesca", "Marseille"]
|
|
856
|
+
cities_list3 = ["Belp", "Bad Schwalbach", "Edinburgh", "Hilversum"]
|
|
857
|
+
cities_type1 = {
|
|
858
|
+
"cities_list": cities_list1,
|
|
859
|
+
"font": font_path,
|
|
860
|
+
"font_size": 26,
|
|
861
|
+
"symbol": "circle",
|
|
862
|
+
"ptsize": 24,
|
|
863
|
+
"outline": "black",
|
|
864
|
+
"fill": "red",
|
|
865
|
+
"box_outline": "black",
|
|
866
|
+
}
|
|
867
|
+
cities_type2 = {
|
|
868
|
+
"cities_list": cities_list2,
|
|
869
|
+
"font": font_path,
|
|
870
|
+
"font_size": 24,
|
|
871
|
+
"symbol": "pentagon",
|
|
872
|
+
"ptsize": 24,
|
|
873
|
+
"outline": "red",
|
|
874
|
+
"fill": "blue",
|
|
875
|
+
"box_outline": "black",
|
|
876
|
+
}
|
|
877
|
+
cities_type3 = {
|
|
878
|
+
"cities_list": cities_list3,
|
|
879
|
+
"font": font_path,
|
|
880
|
+
"font_size": 22,
|
|
881
|
+
"symbol": "star5",
|
|
882
|
+
"ptsize": 35,
|
|
883
|
+
"outline": "green",
|
|
884
|
+
"fill": "yellow",
|
|
885
|
+
"box_outline": "black",
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
overlays["cities"] = [cities_type1, cities_type2, cities_type3]
|
|
889
|
+
|
|
890
|
+
img = cw_pil.add_overlay_from_dict(overlays, area_def, background=img)
|
|
891
|
+
|
|
892
|
+
assert images_match(grid_img, img), "Writing of nh_cities_from_dict_pil failed"
|
|
893
|
+
|
|
894
|
+
def test_add_shapefiles_from_dict_pil(self, cw_pil, new_test_image):
|
|
895
|
+
filename = "two_shapefiles_pil.png"
|
|
896
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
897
|
+
|
|
898
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
899
|
+
area_def = south_america()
|
|
900
|
+
|
|
901
|
+
overlays = {}
|
|
902
|
+
overlays["coasts"] = {"level": 4, "resolution": "l"}
|
|
903
|
+
overlays["shapefiles"] = [
|
|
904
|
+
{
|
|
905
|
+
"filename": os.path.join(LOCAL_DIR, "test_data/shapes/Metareas.shp"),
|
|
906
|
+
"outline": "magenta",
|
|
907
|
+
"width": 2.5,
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
"filename": os.path.join(
|
|
911
|
+
LOCAL_DIR,
|
|
912
|
+
"test_data/shapes/divisao_politica/BR_Regioes.shp",
|
|
913
|
+
),
|
|
914
|
+
"outline": "red",
|
|
915
|
+
"fill": "yellow",
|
|
916
|
+
"fill_opacity": 50,
|
|
917
|
+
},
|
|
918
|
+
]
|
|
919
|
+
|
|
920
|
+
img = cw_pil.add_overlay_from_dict(overlays, area_def, background=img)
|
|
921
|
+
|
|
922
|
+
assert images_match(grid_img, img), "Writing of two shapefiles from dict pil failed"
|
|
923
|
+
|
|
924
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
925
|
+
def test_add_one_shapefile_from_cfg_pil(self, cw_pil, new_test_image):
|
|
926
|
+
config_file = os.path.join(LOCAL_DIR, "nh_one_shapefile.ini")
|
|
927
|
+
filename = "one_shapefile_from_cfg_pil.png"
|
|
928
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
929
|
+
|
|
930
|
+
img = new_test_image("RGB", (425, 425), filename)
|
|
931
|
+
area_def = south_america()
|
|
932
|
+
|
|
933
|
+
cw_pil.add_overlay_from_config(config_file, area_def, img)
|
|
934
|
+
|
|
935
|
+
assert images_match(grid_img, img), "Writing one shapefile from cfg pil failed"
|
|
936
|
+
|
|
937
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
938
|
+
def test_add_grid_from_dict_pil(self, cw_pil, new_test_image):
|
|
939
|
+
filename = "grid_from_dict_pil.png"
|
|
940
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, filename))
|
|
941
|
+
|
|
942
|
+
img = new_test_image("RGB", (800, 800), filename)
|
|
943
|
+
area_def = uk_and_ireland()
|
|
944
|
+
|
|
945
|
+
font = ImageFont.truetype(font_path, 40)
|
|
946
|
+
|
|
947
|
+
overlays = {}
|
|
948
|
+
overlays["coasts"] = {"width": 3.0, "level": 4, "resolution": "l"}
|
|
949
|
+
overlays["grid"] = {
|
|
950
|
+
"major_lonlat": (5, 5),
|
|
951
|
+
"minor_lonlat": (1, 1),
|
|
952
|
+
"outline": (255, 0, 0),
|
|
953
|
+
"outline_opacity": 127,
|
|
954
|
+
"minor_outline": (0, 0, 255),
|
|
955
|
+
"minor_outline_opacity": 127,
|
|
956
|
+
"width": 10.5,
|
|
957
|
+
"minor_width": 5.5,
|
|
958
|
+
"minor_is_tick": False,
|
|
959
|
+
"write_text": True,
|
|
960
|
+
"lat_placement": "lr",
|
|
961
|
+
"lon_placement": "b",
|
|
962
|
+
"font": font,
|
|
963
|
+
"fill": "yellow",
|
|
964
|
+
}
|
|
965
|
+
# Fill is pil text color! Pil Font can be None, then a of default font is choosen
|
|
966
|
+
|
|
967
|
+
img = cw_pil.add_overlay_from_dict(overlays, area_def, background=img)
|
|
968
|
+
|
|
969
|
+
assert images_match(grid_img, img), "Writing grid from dict pil failed"
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
@pytest.mark.parametrize(
|
|
973
|
+
"cw, filename, area_def, specific_kwargs",
|
|
974
|
+
[
|
|
975
|
+
(
|
|
976
|
+
lazy_fixture("cw_pil"),
|
|
977
|
+
"western_shapes_pil.png",
|
|
978
|
+
north_atlantic(),
|
|
979
|
+
dict(font=pil_font_16, fill="yellow", outline="red", minor_outline="red"),
|
|
980
|
+
),
|
|
981
|
+
(
|
|
982
|
+
lazy_fixture("cw_pil"),
|
|
983
|
+
"eastern_shapes_pil.png",
|
|
984
|
+
eurasia(),
|
|
985
|
+
dict(font=pil_font_20, fill="yellow", outline="red", minor_outline="red"),
|
|
986
|
+
),
|
|
987
|
+
(
|
|
988
|
+
lazy_fixture("cw_agg"),
|
|
989
|
+
"western_shapes_agg.png",
|
|
990
|
+
north_atlantic(),
|
|
991
|
+
dict(
|
|
992
|
+
font=agg_font_20_orange,
|
|
993
|
+
outline="blue",
|
|
994
|
+
width=5.0,
|
|
995
|
+
outline_opacity=100,
|
|
996
|
+
minor_outline="blue",
|
|
997
|
+
minor_width=5.0,
|
|
998
|
+
minor_outline_opacity=200,
|
|
999
|
+
),
|
|
1000
|
+
),
|
|
1001
|
+
(
|
|
1002
|
+
lazy_fixture("cw_agg"),
|
|
1003
|
+
"eastern_shapes_agg.png",
|
|
1004
|
+
eurasia(),
|
|
1005
|
+
dict(
|
|
1006
|
+
font=agg_font_20_orange,
|
|
1007
|
+
outline="blue",
|
|
1008
|
+
width=5.0,
|
|
1009
|
+
outline_opacity=100,
|
|
1010
|
+
minor_outline="blue",
|
|
1011
|
+
minor_width=5.0,
|
|
1012
|
+
minor_outline_opacity=200,
|
|
1013
|
+
),
|
|
1014
|
+
),
|
|
1015
|
+
],
|
|
1016
|
+
)
|
|
1017
|
+
def test_shapes(new_test_image, cw, filename, area_def, specific_kwargs):
|
|
1018
|
+
"""Test western/eastern shapes."""
|
|
1019
|
+
result_file = os.path.join(LOCAL_DIR, filename)
|
|
1020
|
+
grid_img = Image.open(result_file)
|
|
1021
|
+
|
|
1022
|
+
img = new_test_image("RGB", (1000, 560), filename)
|
|
1023
|
+
|
|
1024
|
+
cw.add_coastlines(img, area_def, resolution="l", level=2)
|
|
1025
|
+
|
|
1026
|
+
cw.add_grid(
|
|
1027
|
+
img,
|
|
1028
|
+
area_def,
|
|
1029
|
+
(10.0, 10.0),
|
|
1030
|
+
(5.0, 5.0),
|
|
1031
|
+
write_text=True,
|
|
1032
|
+
lon_placement="lbr",
|
|
1033
|
+
lat_placement="",
|
|
1034
|
+
**specific_kwargs,
|
|
1035
|
+
)
|
|
1036
|
+
|
|
1037
|
+
assert images_match(grid_img, img), "Writing of shapes failed"
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
@pytest.mark.parametrize(
|
|
1041
|
+
"cw, filename, shape, area_def, specific_kwargs",
|
|
1042
|
+
[
|
|
1043
|
+
( # lon=175 +/-40, lat=16..65 | Avoid Eurasia scratch with asymmetric area_extent
|
|
1044
|
+
lazy_fixture("cw_pil"),
|
|
1045
|
+
"no_h_scratch_pil.png",
|
|
1046
|
+
(888, 781),
|
|
1047
|
+
bering_straight(),
|
|
1048
|
+
dict(font=pil_font_20, fill="yellow", outline="orange", minor_outline="orange"),
|
|
1049
|
+
),
|
|
1050
|
+
( # lon=155+/-30 lat=-5..45 | No Eurasia problem (Eurasia has always lat > 0.0)
|
|
1051
|
+
lazy_fixture("cw_pil"),
|
|
1052
|
+
"no_v_scratch_pil.png",
|
|
1053
|
+
(888, 705),
|
|
1054
|
+
hawaii(),
|
|
1055
|
+
dict(font=pil_font_20, fill="yellow", outline="orange", minor_outline="orange"),
|
|
1056
|
+
),
|
|
1057
|
+
( # lon=175 +/-40, lat=16..65 | Avoid Eurasia scratch with asymmetric area_extent
|
|
1058
|
+
lazy_fixture("cw_agg"),
|
|
1059
|
+
"no_h_scratch_agg.png",
|
|
1060
|
+
(888, 781),
|
|
1061
|
+
bering_straight(),
|
|
1062
|
+
dict(
|
|
1063
|
+
font=agg_font_20_yellow,
|
|
1064
|
+
outline="green",
|
|
1065
|
+
width=5.0,
|
|
1066
|
+
outline_opacity=100,
|
|
1067
|
+
minor_outline="green",
|
|
1068
|
+
minor_width=5.0,
|
|
1069
|
+
minor_outline_opacity=200,
|
|
1070
|
+
),
|
|
1071
|
+
),
|
|
1072
|
+
( # lon=155+/-30 lat=-5..45 | No Eurasia problem (Eurasia has always lat > 0.0)
|
|
1073
|
+
lazy_fixture("cw_agg"),
|
|
1074
|
+
"no_v_scratch_agg.png",
|
|
1075
|
+
(888, 705),
|
|
1076
|
+
hawaii(),
|
|
1077
|
+
dict(
|
|
1078
|
+
font=agg_font_20_yellow,
|
|
1079
|
+
outline="green",
|
|
1080
|
+
width=5.0,
|
|
1081
|
+
outline_opacity=100,
|
|
1082
|
+
minor_outline="green",
|
|
1083
|
+
minor_width=5.0,
|
|
1084
|
+
minor_outline_opacity=200,
|
|
1085
|
+
),
|
|
1086
|
+
),
|
|
1087
|
+
],
|
|
1088
|
+
)
|
|
1089
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
1090
|
+
def test_no_scratch(new_test_image, cw, filename, shape, area_def, specific_kwargs):
|
|
1091
|
+
"""Test no scratches are visible."""
|
|
1092
|
+
result_file = os.path.join(LOCAL_DIR, filename)
|
|
1093
|
+
grid_img = Image.open(result_file)
|
|
1094
|
+
|
|
1095
|
+
img = new_test_image("RGB", shape, filename)
|
|
1096
|
+
|
|
1097
|
+
cw.add_coastlines(img, area_def, resolution="l", level=2)
|
|
1098
|
+
|
|
1099
|
+
cw.add_grid(
|
|
1100
|
+
img,
|
|
1101
|
+
area_def,
|
|
1102
|
+
(10.0, 10.0),
|
|
1103
|
+
(5.0, 5.0),
|
|
1104
|
+
write_text=True,
|
|
1105
|
+
lon_placement="bt",
|
|
1106
|
+
lat_placement="lr",
|
|
1107
|
+
**specific_kwargs,
|
|
1108
|
+
)
|
|
1109
|
+
cw.add_rivers(img, area_def, level=5, outline="blue")
|
|
1110
|
+
cw.add_borders(img, area_def, outline="red")
|
|
1111
|
+
|
|
1112
|
+
assert images_match(grid_img, img), "Writing of no_scratch failed"
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
class TestContourWriterAGG(_ContourWriterTestBase):
|
|
1116
|
+
"""Test AGG contour writer."""
|
|
354
1117
|
|
|
355
1118
|
def test_europe_agg(self):
|
|
356
1119
|
from pycoast import ContourWriterAGG
|
|
357
|
-
|
|
358
|
-
|
|
1120
|
+
|
|
1121
|
+
euro_img = Image.open(os.path.join(LOCAL_DIR, "contours_europe_agg.png"))
|
|
359
1122
|
euro_data = np.array(euro_img)
|
|
360
1123
|
|
|
361
|
-
img = Image.new(
|
|
362
|
-
proj4_string =
|
|
363
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
1124
|
+
img = Image.new("RGB", (640, 480))
|
|
1125
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
364
1126
|
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
365
1127
|
area_def = (proj4_string, area_extent)
|
|
366
1128
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
367
|
-
cw.add_coastlines(img, area_def, resolution=
|
|
368
|
-
cw.add_rivers(img, area_def, level=5, outline=
|
|
369
|
-
|
|
370
|
-
cw.add_borders(img, area_def, outline=(255, 0, 0),
|
|
371
|
-
width=3, outline_opacity=32)
|
|
1129
|
+
cw.add_coastlines(img, area_def, resolution="l", level=4)
|
|
1130
|
+
cw.add_rivers(img, area_def, level=5, outline="blue", width=0.5, outline_opacity=127)
|
|
1131
|
+
cw.add_borders(img, area_def, outline=(255, 0, 0), width=3, outline_opacity=32)
|
|
372
1132
|
res = np.array(img)
|
|
373
|
-
|
|
374
|
-
'Writing of contours failed for AGG')
|
|
1133
|
+
assert fft_metric(euro_data, res), "Writing of contours failed for AGG"
|
|
375
1134
|
|
|
376
1135
|
def test_europe_agg_file(self):
|
|
377
1136
|
from pycoast import ContourWriterAGG
|
|
378
|
-
|
|
379
|
-
|
|
1137
|
+
|
|
1138
|
+
euro_img = Image.open(os.path.join(LOCAL_DIR, "contours_europe_agg.png"))
|
|
380
1139
|
euro_data = np.array(euro_img)
|
|
381
1140
|
|
|
382
|
-
proj4_string =
|
|
383
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
1141
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
384
1142
|
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
385
1143
|
area_def = (proj4_string, area_extent)
|
|
386
1144
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
387
|
-
cw.add_coastlines_to_file(
|
|
388
|
-
cw.add_rivers_to_file(
|
|
389
|
-
|
|
390
|
-
cw.add_borders_to_file(test_file, area_def, outline=(255, 0, 0),
|
|
391
|
-
width=3, outline_opacity=32)
|
|
1145
|
+
cw.add_coastlines_to_file(test_filename, area_def, resolution="l", level=4)
|
|
1146
|
+
cw.add_rivers_to_file(test_filename, area_def, level=5, outline="blue", width=0.5, outline_opacity=127)
|
|
1147
|
+
cw.add_borders_to_file(test_filename, area_def, outline=(255, 0, 0), width=3, outline_opacity=32)
|
|
392
1148
|
|
|
393
|
-
img = Image.open(
|
|
1149
|
+
img = Image.open(test_filename)
|
|
394
1150
|
res = np.array(img)
|
|
395
|
-
|
|
396
|
-
'Writing of contours failed for AGG')
|
|
1151
|
+
assert fft_metric(euro_data, res), "Writing of contours failed for AGG"
|
|
397
1152
|
|
|
398
1153
|
def test_geos_agg(self):
|
|
399
1154
|
from pycoast import ContourWriterAGG
|
|
400
|
-
|
|
401
|
-
|
|
1155
|
+
|
|
1156
|
+
geos_img = Image.open(os.path.join(LOCAL_DIR, "contours_geos_agg.png"))
|
|
402
1157
|
geos_data = np.array(geos_img)
|
|
403
1158
|
|
|
404
|
-
img = Image.new(
|
|
405
|
-
proj4_string =
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
1159
|
+
img = Image.new("RGB", (425, 425))
|
|
1160
|
+
proj4_string = "+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0"
|
|
1161
|
+
area_extent = (
|
|
1162
|
+
-5570248.4773392612,
|
|
1163
|
+
-5567248.074173444,
|
|
1164
|
+
5567248.074173444,
|
|
1165
|
+
5570248.4773392612,
|
|
1166
|
+
)
|
|
409
1167
|
# area_def = (proj4_string, area_extent)
|
|
410
1168
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
411
|
-
cw.add_coastlines(img, (proj4_string, area_extent),
|
|
412
|
-
resolution='l', width=0.5)
|
|
1169
|
+
cw.add_coastlines(img, (proj4_string, area_extent), resolution="l", width=0.5)
|
|
413
1170
|
res = np.array(img)
|
|
414
|
-
|
|
415
|
-
'Writing of geos contours failed for AGG')
|
|
1171
|
+
assert fft_metric(geos_data, res), "Writing of geos contours failed for AGG"
|
|
416
1172
|
|
|
417
1173
|
def test_grid_agg(self):
|
|
418
1174
|
from pycoast import ContourWriterAGG
|
|
419
|
-
|
|
420
|
-
|
|
1175
|
+
|
|
1176
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "grid_europe_agg.png"))
|
|
421
1177
|
grid_data = np.array(grid_img)
|
|
422
1178
|
|
|
423
|
-
img = Image.new(
|
|
424
|
-
proj4_string =
|
|
425
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
1179
|
+
img = Image.new("RGB", (640, 480))
|
|
1180
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
426
1181
|
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
427
1182
|
area_def = (proj4_string, area_extent)
|
|
428
1183
|
|
|
429
1184
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
430
1185
|
|
|
431
|
-
cw.add_coastlines(img, area_def, resolution=
|
|
432
|
-
cw.add_grid(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
1186
|
+
cw.add_coastlines(img, area_def, resolution="l", level=4)
|
|
1187
|
+
cw.add_grid(
|
|
1188
|
+
img,
|
|
1189
|
+
area_def,
|
|
1190
|
+
(10.0, 10.0),
|
|
1191
|
+
(2.0, 2.0),
|
|
1192
|
+
write_text=False,
|
|
1193
|
+
outline="blue",
|
|
1194
|
+
outline_opacity=255,
|
|
1195
|
+
width=1.0,
|
|
1196
|
+
minor_outline="white",
|
|
1197
|
+
minor_outline_opacity=255,
|
|
1198
|
+
minor_width=0.5,
|
|
1199
|
+
minor_is_tick=False,
|
|
1200
|
+
)
|
|
436
1201
|
|
|
437
1202
|
res = np.array(img)
|
|
438
|
-
|
|
439
|
-
fft_metric(grid_data, res), 'Writing of grid failed for AGG')
|
|
1203
|
+
assert fft_metric(grid_data, res), "Writing of grid failed for AGG"
|
|
440
1204
|
|
|
441
1205
|
def test_grid_agg_txt(self):
|
|
442
1206
|
from pycoast import ContourWriterAGG
|
|
443
|
-
import aggdraw
|
|
444
|
-
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
|
|
445
|
-
'grid_europe_agg_txt.png'))
|
|
446
|
-
grid_data = np.array(grid_img)
|
|
447
1207
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
1208
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "grid_europe_agg_txt.png"))
|
|
1209
|
+
|
|
1210
|
+
img = Image.new("RGB", (640, 480))
|
|
1211
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
451
1212
|
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
452
1213
|
area_def = (proj4_string, area_extent)
|
|
453
1214
|
|
|
454
1215
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
455
1216
|
|
|
456
|
-
cw.add_coastlines(img, area_def, resolution=
|
|
457
|
-
font = aggdraw.Font(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
1217
|
+
cw.add_coastlines(img, area_def, resolution="l", level=4)
|
|
1218
|
+
font = aggdraw.Font(
|
|
1219
|
+
"blue",
|
|
1220
|
+
font_path,
|
|
1221
|
+
size=16,
|
|
1222
|
+
opacity=200,
|
|
1223
|
+
)
|
|
1224
|
+
cw.add_grid(
|
|
1225
|
+
img,
|
|
1226
|
+
area_def,
|
|
1227
|
+
(10.0, 10.0),
|
|
1228
|
+
(2.0, 2.0),
|
|
1229
|
+
font=font,
|
|
1230
|
+
outline="blue",
|
|
1231
|
+
outline_opacity=255,
|
|
1232
|
+
width=1.0,
|
|
1233
|
+
minor_outline="white",
|
|
1234
|
+
minor_outline_opacity=255,
|
|
1235
|
+
minor_width=0.5,
|
|
1236
|
+
minor_is_tick=False,
|
|
1237
|
+
)
|
|
1238
|
+
|
|
1239
|
+
assert images_match(grid_img, img), "Writing of grid failed for AGG"
|
|
469
1240
|
|
|
470
1241
|
def test_grid_geos_agg(self):
|
|
471
1242
|
from pycoast import ContourWriterAGG
|
|
472
|
-
|
|
473
|
-
|
|
1243
|
+
|
|
1244
|
+
geos_img = Image.open(os.path.join(LOCAL_DIR, "grid_geos_agg.png"))
|
|
474
1245
|
geos_data = np.array(geos_img)
|
|
475
|
-
img = Image.new(
|
|
476
|
-
proj4_string =
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
1246
|
+
img = Image.new("RGB", (425, 425))
|
|
1247
|
+
proj4_string = "+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0"
|
|
1248
|
+
area_extent = (
|
|
1249
|
+
-5570248.4773392612,
|
|
1250
|
+
-5567248.074173444,
|
|
1251
|
+
5567248.074173444,
|
|
1252
|
+
5570248.4773392612,
|
|
1253
|
+
)
|
|
480
1254
|
area_def = (proj4_string, area_extent)
|
|
481
1255
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
482
|
-
cw.add_coastlines(img, area_def, resolution=
|
|
483
|
-
cw.add_grid(
|
|
484
|
-
|
|
485
|
-
|
|
1256
|
+
cw.add_coastlines(img, area_def, resolution="l")
|
|
1257
|
+
cw.add_grid(
|
|
1258
|
+
img,
|
|
1259
|
+
area_def,
|
|
1260
|
+
(10.0, 10.0),
|
|
1261
|
+
(2.0, 2.0),
|
|
1262
|
+
fill="blue",
|
|
1263
|
+
outline="blue",
|
|
1264
|
+
minor_outline="blue",
|
|
1265
|
+
write_text=False,
|
|
1266
|
+
)
|
|
486
1267
|
|
|
487
1268
|
res = np.array(img)
|
|
488
|
-
|
|
489
|
-
fft_metric(geos_data, res), 'Writing of geos contours failed')
|
|
1269
|
+
assert fft_metric(geos_data, res), "Writing of geos contours failed"
|
|
490
1270
|
|
|
491
1271
|
def test_grid_agg_file(self):
|
|
492
1272
|
from pycoast import ContourWriterAGG
|
|
493
|
-
|
|
494
|
-
|
|
1273
|
+
|
|
1274
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "grid_europe_agg.png"))
|
|
495
1275
|
grid_data = np.array(grid_img)
|
|
496
1276
|
|
|
497
|
-
proj4_string =
|
|
498
|
-
'+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
|
|
1277
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
499
1278
|
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
500
1279
|
area_def = (proj4_string, area_extent)
|
|
501
1280
|
|
|
502
1281
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
503
1282
|
|
|
504
|
-
cw.add_coastlines_to_file(
|
|
505
|
-
cw.add_grid_to_file(
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
1283
|
+
cw.add_coastlines_to_file(grid_filename, area_def, resolution="l", level=4)
|
|
1284
|
+
cw.add_grid_to_file(
|
|
1285
|
+
grid_filename,
|
|
1286
|
+
area_def,
|
|
1287
|
+
(10.0, 10.0),
|
|
1288
|
+
(2.0, 2.0),
|
|
1289
|
+
write_text=False,
|
|
1290
|
+
outline="blue",
|
|
1291
|
+
outline_opacity=255,
|
|
1292
|
+
width=1.0,
|
|
1293
|
+
minor_outline="white",
|
|
1294
|
+
minor_outline_opacity=255,
|
|
1295
|
+
minor_width=0.5,
|
|
1296
|
+
minor_is_tick=False,
|
|
1297
|
+
)
|
|
1298
|
+
img = Image.open(grid_filename)
|
|
511
1299
|
res = np.array(img)
|
|
512
|
-
|
|
513
|
-
fft_metric(grid_data, res), 'Writing of grid failed for AGG')
|
|
1300
|
+
assert fft_metric(grid_data, res), "Writing of grid failed for AGG"
|
|
514
1301
|
|
|
515
1302
|
def test_grid_nh_agg(self):
|
|
516
1303
|
from pycoast import ContourWriterAGG
|
|
517
|
-
|
|
518
|
-
grid_img = Image.open(os.path.join(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
|
|
523
|
-
area_extent = (-5326849.0625, -5326849.0625,
|
|
524
|
-
5326849.0625, 5326849.0625)
|
|
1304
|
+
|
|
1305
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "grid_nh_agg.png"))
|
|
1306
|
+
img = Image.new("RGB", (425, 425))
|
|
1307
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
1308
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
525
1309
|
area_def = (proj4_string, area_extent)
|
|
526
1310
|
|
|
527
1311
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
528
1312
|
|
|
529
|
-
cw.add_coastlines(img, area_def, resolution=
|
|
530
|
-
font = aggdraw.Font(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
1313
|
+
cw.add_coastlines(img, area_def, resolution="l", level=4)
|
|
1314
|
+
font = aggdraw.Font(
|
|
1315
|
+
"blue",
|
|
1316
|
+
font_path,
|
|
1317
|
+
size=10,
|
|
1318
|
+
)
|
|
1319
|
+
cw.add_grid(
|
|
1320
|
+
img,
|
|
1321
|
+
area_def,
|
|
1322
|
+
(10.0, 10.0),
|
|
1323
|
+
(2.0, 2.0),
|
|
1324
|
+
font=font,
|
|
1325
|
+
fill="blue",
|
|
1326
|
+
outline="blue",
|
|
1327
|
+
minor_outline="blue",
|
|
1328
|
+
lon_placement="tblr",
|
|
1329
|
+
lat_placement="",
|
|
1330
|
+
)
|
|
539
1331
|
|
|
540
1332
|
# NOTE: Experience inconsistency in ttf font writing between systems.
|
|
541
1333
|
# Still trying to figure out why this test sometimes fails to write
|
|
542
1334
|
# correct font markings.
|
|
543
|
-
|
|
544
|
-
'Writing of nh grid failed for AGG')
|
|
1335
|
+
assert images_match(grid_img, img), "Writing of nh grid failed for AGG"
|
|
545
1336
|
|
|
546
1337
|
def test_add_polygon_agg(self):
|
|
547
1338
|
from pycoast import ContourWriterAGG
|
|
548
|
-
|
|
549
|
-
|
|
1339
|
+
|
|
1340
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "nh_polygons_agg.png"))
|
|
550
1341
|
grid_data = np.array(grid_img)
|
|
551
1342
|
|
|
552
|
-
img = Image.new(
|
|
553
|
-
proj4_string =
|
|
554
|
-
area_extent = (-5326849.0625, -5326849.0625,
|
|
555
|
-
5326849.0625, 5326849.0625)
|
|
1343
|
+
img = Image.new("RGB", (425, 425))
|
|
1344
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
1345
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
556
1346
|
area_def = (proj4_string, area_extent)
|
|
557
1347
|
|
|
558
1348
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
559
1349
|
|
|
560
1350
|
polygons = {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
1351
|
+
"REYKJAVIK_ATC_A": (
|
|
1352
|
+
(-20.0, 73.0),
|
|
1353
|
+
(0.0, 73.0),
|
|
1354
|
+
(0.0, 61.0),
|
|
1355
|
+
(-30.0, 61.0),
|
|
1356
|
+
(-39.0, 63.5),
|
|
1357
|
+
(-20, 70),
|
|
1358
|
+
),
|
|
1359
|
+
"REYKJAVIK_ATC_B": (
|
|
1360
|
+
(-39, 63.5),
|
|
1361
|
+
(-55 + 4 / 6.0, 63.5),
|
|
1362
|
+
(-57 + 45 / 60.0, 65),
|
|
1363
|
+
(-76, 76),
|
|
1364
|
+
(-75, 78),
|
|
1365
|
+
(-60, 82),
|
|
1366
|
+
(0, 90),
|
|
1367
|
+
(30, 82),
|
|
1368
|
+
(0, 82),
|
|
1369
|
+
(0, 73),
|
|
1370
|
+
(-20, 73),
|
|
1371
|
+
(-20, 70),
|
|
1372
|
+
),
|
|
1373
|
+
"REYKJAVIK_ATC": (
|
|
1374
|
+
(0.0, 73.0),
|
|
1375
|
+
(0.0, 61.0),
|
|
1376
|
+
(-30.0, 61.0),
|
|
1377
|
+
(-39, 63.5),
|
|
1378
|
+
(-55 + 4 / 6.0, 63.5),
|
|
1379
|
+
(-57 + 45 / 60.0, 65),
|
|
1380
|
+
(-76, 76),
|
|
1381
|
+
(-75, 78),
|
|
1382
|
+
(-60, 82),
|
|
1383
|
+
(0, 90),
|
|
1384
|
+
(30, 82),
|
|
1385
|
+
(0, 82),
|
|
1386
|
+
),
|
|
1387
|
+
"ICELAND_BOX": ((-25, 62.5), (-25, 67), (-13, 67), (-13, 62.5)),
|
|
572
1388
|
}
|
|
573
1389
|
|
|
574
|
-
cw.add_polygon(img, area_def, polygons[
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
1390
|
+
cw.add_polygon(img, area_def, polygons["REYKJAVIK_ATC"], outline="red", width=2)
|
|
1391
|
+
cw.add_polygon(
|
|
1392
|
+
img,
|
|
1393
|
+
area_def,
|
|
1394
|
+
polygons["ICELAND_BOX"],
|
|
1395
|
+
outline="green",
|
|
1396
|
+
fill="gray",
|
|
1397
|
+
width=2,
|
|
1398
|
+
)
|
|
1399
|
+
cw.add_coastlines(img, area_def, resolution="l", level=4)
|
|
579
1400
|
|
|
580
1401
|
res = np.array(img)
|
|
581
|
-
|
|
582
|
-
|
|
1402
|
+
assert fft_metric(grid_data, res), "Writing of nh polygons failed"
|
|
1403
|
+
|
|
1404
|
+
def test_add_points_agg(self):
|
|
1405
|
+
from pyresample.geometry import AreaDefinition
|
|
1406
|
+
|
|
1407
|
+
from pycoast import ContourWriterAGG
|
|
1408
|
+
|
|
1409
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "nh_points_agg.png"))
|
|
1410
|
+
grid_data = np.array(grid_img)
|
|
1411
|
+
|
|
1412
|
+
img = Image.new("RGB", (1024, 1024), (255, 255, 255))
|
|
1413
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
1414
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
1415
|
+
|
|
1416
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
1417
|
+
|
|
1418
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1419
|
+
cw.add_coastlines(img, area_def, outline="black", resolution="l", level=4)
|
|
1420
|
+
cw.add_borders(img, area_def, outline="black", width=3, level=1, resolution="c")
|
|
1421
|
+
|
|
1422
|
+
points_list = [((2.3522, 48.8566), "Paris"), ((0.1278, 51.5074), "London")]
|
|
1423
|
+
cw.add_points(
|
|
1424
|
+
img,
|
|
1425
|
+
area_def,
|
|
1426
|
+
points_list=points_list,
|
|
1427
|
+
font_file=font_path,
|
|
1428
|
+
symbol="circle",
|
|
1429
|
+
ptsize=16,
|
|
1430
|
+
outline="black",
|
|
1431
|
+
width=3,
|
|
1432
|
+
fill="red",
|
|
1433
|
+
fill_opacity=128,
|
|
1434
|
+
box_outline="blue",
|
|
1435
|
+
box_linewidth=0.5,
|
|
1436
|
+
box_fill="yellow",
|
|
1437
|
+
box_opacity=200,
|
|
1438
|
+
)
|
|
1439
|
+
|
|
1440
|
+
res = np.array(img)
|
|
1441
|
+
assert fft_metric(grid_data, res), "Writing of nh points failed"
|
|
583
1442
|
|
|
584
1443
|
def test_add_shapefile_shapes_agg(self):
|
|
585
1444
|
from pycoast import ContourWriterAGG
|
|
586
|
-
|
|
587
|
-
|
|
1445
|
+
|
|
1446
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "brazil_shapefiles_agg.png"))
|
|
588
1447
|
grid_data = np.array(grid_img)
|
|
589
1448
|
|
|
590
|
-
img = Image.new(
|
|
591
|
-
proj4_string =
|
|
592
|
-
'+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m'
|
|
1449
|
+
img = Image.new("RGB", (425, 425))
|
|
1450
|
+
proj4_string = "+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m"
|
|
593
1451
|
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
|
|
594
1452
|
area_def = (proj4_string, area_extent)
|
|
595
1453
|
|
|
596
1454
|
cw = ContourWriterAGG(gshhs_root_dir)
|
|
597
1455
|
|
|
598
|
-
cw.add_coastlines(img, area_def, resolution=
|
|
599
|
-
cw.add_shapefile_shapes(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
1456
|
+
cw.add_coastlines(img, area_def, resolution="l", level=4)
|
|
1457
|
+
cw.add_shapefile_shapes(
|
|
1458
|
+
img,
|
|
1459
|
+
area_def,
|
|
1460
|
+
os.path.join(LOCAL_DIR, "test_data/shapes/Metareas.shp"),
|
|
1461
|
+
outline="red",
|
|
1462
|
+
width=2,
|
|
1463
|
+
)
|
|
1464
|
+
cw.add_shapefile_shape(
|
|
1465
|
+
img,
|
|
1466
|
+
area_def,
|
|
1467
|
+
os.path.join(
|
|
1468
|
+
LOCAL_DIR,
|
|
1469
|
+
"test_data/shapes/divisao_politica/BR_Regioes.shp",
|
|
1470
|
+
),
|
|
1471
|
+
3,
|
|
1472
|
+
outline="blue",
|
|
1473
|
+
)
|
|
1474
|
+
cw.add_shapefile_shape(
|
|
1475
|
+
img,
|
|
1476
|
+
area_def,
|
|
1477
|
+
os.path.join(
|
|
1478
|
+
LOCAL_DIR,
|
|
1479
|
+
"test_data/shapes/divisao_politica/BR_Regioes.shp",
|
|
1480
|
+
),
|
|
1481
|
+
4,
|
|
1482
|
+
outline="blue",
|
|
1483
|
+
fill="green",
|
|
1484
|
+
)
|
|
1485
|
+
|
|
1486
|
+
res = np.array(img)
|
|
1487
|
+
assert fft_metric(grid_data, res), "Writing of Brazil shapefiles failed"
|
|
1488
|
+
|
|
1489
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
1490
|
+
def test_config_file_coasts_and_grid(self):
|
|
1491
|
+
from pyresample.geometry import AreaDefinition
|
|
1492
|
+
|
|
1493
|
+
from pycoast import ContourWriterAGG
|
|
1494
|
+
|
|
1495
|
+
overlay_config = os.path.join(LOCAL_DIR, "coasts_and_grid_agg.ini")
|
|
1496
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "grid_nh_cfg_agg.png"))
|
|
1497
|
+
proj_dict = {
|
|
1498
|
+
"proj": "laea",
|
|
1499
|
+
"lat_0": 90.0,
|
|
1500
|
+
"lon_0": 0.0,
|
|
1501
|
+
"a": 6371228.0,
|
|
1502
|
+
"units": "m",
|
|
1503
|
+
}
|
|
1504
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
1505
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj_dict, 850, 850, area_extent)
|
|
1506
|
+
|
|
1507
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1508
|
+
overlay = cw.add_overlay_from_config(overlay_config, area_def)
|
|
1509
|
+
img = Image.new("RGB", (850, 850), (255, 255, 255))
|
|
1510
|
+
img.paste(overlay, mask=overlay)
|
|
1511
|
+
|
|
1512
|
+
assert images_match(grid_img, img), "Writing of nh cfg grid failed"
|
|
1513
|
+
|
|
1514
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
1515
|
+
def test_config_file_points_and_borders_agg(self):
|
|
1516
|
+
from pyresample.geometry import AreaDefinition
|
|
1517
|
+
|
|
1518
|
+
from pycoast import ContourWriterAGG
|
|
1519
|
+
|
|
1520
|
+
config_file = os.path.join(LOCAL_DIR, "nh_points_agg.ini")
|
|
1521
|
+
|
|
1522
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "nh_points_agg.png"))
|
|
1523
|
+
grid_data = np.array(grid_img)
|
|
1524
|
+
|
|
1525
|
+
img = Image.new("RGB", (1024, 1024), (255, 255, 255))
|
|
1526
|
+
|
|
1527
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
1528
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
1529
|
+
|
|
1530
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
1531
|
+
|
|
1532
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1533
|
+
|
|
1534
|
+
cw.add_overlay_from_config(config_file, area_def, img)
|
|
1535
|
+
|
|
1536
|
+
res = np.array(img)
|
|
1537
|
+
assert fft_metric(grid_data, res), "Add points with agg module from a config file failed"
|
|
1538
|
+
|
|
1539
|
+
def test_coastlines_convert_to_rgba_agg(self):
|
|
1540
|
+
from pycoast import ContourWriterAGG
|
|
1541
|
+
|
|
1542
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
1543
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
1544
|
+
area_def = (proj4_string, area_extent)
|
|
1545
|
+
|
|
1546
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1547
|
+
cw.add_coastlines_to_file(p_coasts_filename, area_def, resolution="l", level=4)
|
|
1548
|
+
|
|
1549
|
+
img = Image.open(p_coasts_filename)
|
|
1550
|
+
image_mode = img.mode
|
|
1551
|
+
img.close()
|
|
1552
|
+
|
|
1553
|
+
assert image_mode == "RGBA", "Conversion to RGBA failed."
|
|
1554
|
+
|
|
1555
|
+
def test_add_cities_agg(self):
|
|
1556
|
+
from pyresample.geometry import AreaDefinition
|
|
1557
|
+
|
|
1558
|
+
from pycoast import ContourWriterAGG
|
|
1559
|
+
|
|
1560
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "nh_cities_agg.png"))
|
|
1561
|
+
grid_data = np.array(grid_img)
|
|
1562
|
+
|
|
1563
|
+
img = Image.new("RGB", (1024, 1024), (255, 255, 255))
|
|
1564
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
1565
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
1566
|
+
|
|
1567
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
1568
|
+
|
|
1569
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1570
|
+
cw.add_coastlines(img, area_def, outline="black", resolution="l", level=4)
|
|
1571
|
+
cw.add_borders(img, area_def, outline="black", width=3, level=1, resolution="c")
|
|
1572
|
+
|
|
1573
|
+
cities_list = ["Zurich", "Oslo", "Reykjavik", "Fairbanks", "Toronto"]
|
|
1574
|
+
cw.add_cities(
|
|
1575
|
+
img,
|
|
1576
|
+
area_def,
|
|
1577
|
+
cities_list=cities_list,
|
|
1578
|
+
font_file=font_path,
|
|
1579
|
+
font_size=20,
|
|
1580
|
+
symbol="square",
|
|
1581
|
+
ptsize=16,
|
|
1582
|
+
outline="black",
|
|
1583
|
+
width=1,
|
|
1584
|
+
fill="blue",
|
|
1585
|
+
fill_opacity=128,
|
|
1586
|
+
box_outline="blue",
|
|
1587
|
+
box_linewidth=0.5,
|
|
1588
|
+
box_fill="yellow",
|
|
1589
|
+
box_opacity=200,
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
res = np.array(img)
|
|
1593
|
+
assert fft_metric(grid_data, res), "Writing of nh cities_agg failed"
|
|
1594
|
+
|
|
1595
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
1596
|
+
def test_add_cities_cfg_agg(self):
|
|
1597
|
+
from pyresample.geometry import AreaDefinition
|
|
1598
|
+
|
|
1599
|
+
from pycoast import ContourWriterAGG
|
|
1600
|
+
|
|
1601
|
+
config_file = os.path.join(LOCAL_DIR, "nh_cities_agg.ini")
|
|
1602
|
+
|
|
1603
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "nh_cities_agg.png"))
|
|
1604
|
+
grid_data = np.array(grid_img)
|
|
1605
|
+
|
|
1606
|
+
img = Image.new("RGB", (1024, 1024), (255, 255, 255))
|
|
1607
|
+
|
|
1608
|
+
proj4_string = "+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m"
|
|
1609
|
+
area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
|
|
1610
|
+
|
|
1611
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
1612
|
+
|
|
1613
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1614
|
+
|
|
1615
|
+
cw.add_overlay_from_config(config_file, area_def, img)
|
|
1616
|
+
|
|
1617
|
+
res = np.array(img)
|
|
1618
|
+
assert fft_metric(grid_data, res), "Writing of nh cities_cfg_agg failed"
|
|
1619
|
+
|
|
1620
|
+
def test_add_cities_from_dict_agg(self):
|
|
1621
|
+
from pyresample.geometry import AreaDefinition
|
|
1622
|
+
|
|
1623
|
+
from pycoast import ContourWriterAGG
|
|
1624
|
+
|
|
1625
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "nh_cities_from_dict_agg.png"))
|
|
1626
|
+
grid_data = np.array(grid_img)
|
|
1627
|
+
|
|
1628
|
+
img = Image.new("RGB", (1024, 1024), (255, 255, 255))
|
|
1629
|
+
|
|
1630
|
+
proj4_string = "+proj=stere +ellps=WGS84 +lat_0=51.5 +lon_0=-0.1"
|
|
1631
|
+
area_extent = (-2000000.0, -2000000.0, 2000000.0, 2000000.0)
|
|
1632
|
+
|
|
1633
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 1024, 1024, area_extent)
|
|
1634
|
+
|
|
1635
|
+
overlays = {}
|
|
1636
|
+
overlays["coasts"] = {"level": 4, "resolution": "l", "outline": "black"}
|
|
1637
|
+
overlays["borders"] = {"level": 1, "outline": "black", "resolution": "c"}
|
|
1638
|
+
cities_list1 = [
|
|
1639
|
+
"Berlin",
|
|
1640
|
+
"Paris",
|
|
1641
|
+
"London",
|
|
1642
|
+
"Dublin",
|
|
1643
|
+
"Madrid",
|
|
1644
|
+
"Reykjavik",
|
|
1645
|
+
"Oslo",
|
|
1646
|
+
"Rome",
|
|
1647
|
+
]
|
|
1648
|
+
cities_list2 = ["Freiburg", "Montelimar", "Huesca", "Marseille"]
|
|
1649
|
+
cities_list3 = ["Belp", "Bad Schwalbach", "Edinburgh", "Hilversum"]
|
|
1650
|
+
cities_type1 = {
|
|
1651
|
+
"cities_list": cities_list1,
|
|
1652
|
+
"font": font_path,
|
|
1653
|
+
"font_size": 26,
|
|
1654
|
+
"symbol": "circle",
|
|
1655
|
+
"ptsize": 24,
|
|
1656
|
+
"outline": "black",
|
|
1657
|
+
"fill": "red",
|
|
1658
|
+
"box_outline": "black",
|
|
1659
|
+
"box_fill": "blue",
|
|
1660
|
+
"box_opacity": 50,
|
|
1661
|
+
"box_linewidth": 2.0,
|
|
1662
|
+
}
|
|
1663
|
+
cities_type2 = {
|
|
1664
|
+
"cities_list": cities_list2,
|
|
1665
|
+
"font": font_path,
|
|
1666
|
+
"font_size": 24,
|
|
1667
|
+
"symbol": "pentagon",
|
|
1668
|
+
"ptsize": 24,
|
|
1669
|
+
"outline": "red",
|
|
1670
|
+
"fill": "blue",
|
|
1671
|
+
"box_outline": "black",
|
|
1672
|
+
"box_fill": "yellow",
|
|
1673
|
+
"box_opacity": 50,
|
|
1674
|
+
"box_linewidth": 2.0,
|
|
1675
|
+
}
|
|
1676
|
+
cities_type3 = {
|
|
1677
|
+
"cities_list": cities_list3,
|
|
1678
|
+
"font": font_path,
|
|
1679
|
+
"font_size": 22,
|
|
1680
|
+
"symbol": "star5",
|
|
1681
|
+
"ptsize": 35,
|
|
1682
|
+
"outline": "green",
|
|
1683
|
+
"fill": "yellow",
|
|
1684
|
+
"box_outline": "black",
|
|
1685
|
+
"box_fill": "red",
|
|
1686
|
+
"box_opacity": 50,
|
|
1687
|
+
"box_linewidth": 2.0,
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
overlays["cities"] = [cities_type1, cities_type2, cities_type3]
|
|
1691
|
+
|
|
1692
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1693
|
+
|
|
1694
|
+
img = cw.add_overlay_from_dict(overlays, area_def, background=img)
|
|
1695
|
+
|
|
1696
|
+
res = np.array(img)
|
|
1697
|
+
assert fft_metric(grid_data, res), "Writing of nh_cities_from_dict_agg failed"
|
|
1698
|
+
|
|
1699
|
+
def test_add_shapefiles_from_dict_agg(self):
|
|
1700
|
+
from pyresample.geometry import AreaDefinition
|
|
1701
|
+
|
|
1702
|
+
from pycoast import ContourWriterAGG
|
|
1703
|
+
|
|
1704
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "two_shapefiles_agg.png"))
|
|
1705
|
+
grid_data = np.array(grid_img)
|
|
1706
|
+
|
|
1707
|
+
img = Image.new("RGB", (425, 425))
|
|
1708
|
+
proj4_string = "+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m"
|
|
1709
|
+
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
|
|
1710
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 425, 425, area_extent)
|
|
1711
|
+
|
|
1712
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1713
|
+
|
|
1714
|
+
overlays = {}
|
|
1715
|
+
overlays["coasts"] = {"level": 4, "resolution": "l"}
|
|
1716
|
+
overlays["shapefiles"] = [
|
|
1717
|
+
{
|
|
1718
|
+
"filename": os.path.join(LOCAL_DIR, "test_data/shapes/Metareas.shp"),
|
|
1719
|
+
"outline": "magenta",
|
|
1720
|
+
"width": 2.5,
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
"filename": os.path.join(
|
|
1724
|
+
LOCAL_DIR,
|
|
1725
|
+
"test_data/shapes/divisao_politica/BR_Regioes.shp",
|
|
1726
|
+
),
|
|
1727
|
+
"outline": "red",
|
|
1728
|
+
"fill": "yellow",
|
|
1729
|
+
"fill_opacity": 50,
|
|
1730
|
+
},
|
|
1731
|
+
]
|
|
1732
|
+
|
|
1733
|
+
img = cw.add_overlay_from_dict(overlays, area_def, background=img)
|
|
1734
|
+
|
|
1735
|
+
res = np.array(img)
|
|
1736
|
+
assert fft_metric(grid_data, res), "Writing two shapefiles from dict agg failed"
|
|
1737
|
+
|
|
1738
|
+
@pytest.mark.usefixtures("cd_test_dir")
|
|
1739
|
+
def test_add_one_shapefile_from_cfg_agg(self):
|
|
1740
|
+
from pyresample.geometry import AreaDefinition
|
|
1741
|
+
|
|
1742
|
+
from pycoast import ContourWriterAGG
|
|
1743
|
+
|
|
1744
|
+
config_file = os.path.join(LOCAL_DIR, "nh_one_shapefile.ini")
|
|
1745
|
+
|
|
1746
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "one_shapefile_from_cfg_agg.png"))
|
|
1747
|
+
grid_data = np.array(grid_img)
|
|
1748
|
+
|
|
1749
|
+
img = Image.new("RGB", (425, 425))
|
|
1750
|
+
proj4_string = "+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m"
|
|
1751
|
+
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
|
|
1752
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 425, 425, area_extent)
|
|
1753
|
+
|
|
1754
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1755
|
+
|
|
1756
|
+
cw.add_overlay_from_config(config_file, area_def, img)
|
|
612
1757
|
|
|
613
1758
|
res = np.array(img)
|
|
614
|
-
|
|
615
|
-
|
|
1759
|
+
assert fft_metric(grid_data, res), "Writing one shapefile from cfg agg failed"
|
|
1760
|
+
|
|
1761
|
+
def test_add_grid_from_dict_agg(self):
|
|
1762
|
+
from pyresample.geometry import AreaDefinition
|
|
1763
|
+
|
|
1764
|
+
from pycoast import ContourWriterAGG
|
|
1765
|
+
|
|
1766
|
+
grid_img = Image.open(os.path.join(LOCAL_DIR, "grid_from_dict_agg.png"))
|
|
1767
|
+
|
|
1768
|
+
img = Image.new("RGB", (800, 800))
|
|
1769
|
+
proj4_string = "+proj=stere +ellps=WGS84 +lon_0=-4.532 +lat_0=54.228"
|
|
1770
|
+
area_extent = (-600000.0, -600000.0, 600000.0, 600000.0)
|
|
1771
|
+
|
|
1772
|
+
area_def = AreaDefinition("nh", "nh", "nh", proj4_string, 800, 800, area_extent)
|
|
1773
|
+
|
|
1774
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1775
|
+
|
|
1776
|
+
font = aggdraw.Font(
|
|
1777
|
+
"yellow",
|
|
1778
|
+
font_path,
|
|
1779
|
+
opacity=255,
|
|
1780
|
+
size=40,
|
|
1781
|
+
)
|
|
1782
|
+
|
|
1783
|
+
overlays = {}
|
|
1784
|
+
overlays["coasts"] = {"width": 3.0, "level": 4, "resolution": "l"}
|
|
1785
|
+
overlays["grid"] = {
|
|
1786
|
+
"major_lonlat": (5, 5),
|
|
1787
|
+
"minor_lonlat": (1, 1),
|
|
1788
|
+
"outline": (255, 0, 0),
|
|
1789
|
+
"outline_opacity": 127,
|
|
1790
|
+
"minor_outline": (0, 0, 255),
|
|
1791
|
+
"minor_outline_opacity": 127,
|
|
1792
|
+
"width": 10.5,
|
|
1793
|
+
"minor_width": 5.5,
|
|
1794
|
+
"minor_is_tick": False,
|
|
1795
|
+
"write_text": True,
|
|
1796
|
+
"lat_placement": "lr",
|
|
1797
|
+
"lon_placement": "b",
|
|
1798
|
+
"font": font,
|
|
1799
|
+
"fill": "red",
|
|
1800
|
+
}
|
|
1801
|
+
# Fill has no agg effect! Agg Font can be None if and only if write_text is set to False
|
|
1802
|
+
|
|
1803
|
+
img = cw.add_overlay_from_dict(overlays, area_def, background=img)
|
|
1804
|
+
|
|
1805
|
+
assert images_match(grid_img, img), "Writing grid from dict agg failed"
|
|
1806
|
+
|
|
1807
|
+
def test_lonlat_pm_change(self):
|
|
1808
|
+
"""Test that a longlat projection with a non-0 prime meridian is handled correctly."""
|
|
1809
|
+
from pyresample.geometry import AreaDefinition
|
|
1810
|
+
|
|
1811
|
+
from pycoast import ContourWriterAGG
|
|
1812
|
+
|
|
1813
|
+
area_def1 = AreaDefinition("", "", "", "+proj=longlat", 640, 480, (-55.0, -35.0, -5.0, 3.0))
|
|
1814
|
+
area_def2 = AreaDefinition("", "", "", "+proj=longlat +pm=180", 640, 480, (-55.0, -35.0, -5.0, 3.0))
|
|
1815
|
+
area_def3 = AreaDefinition("", "", "", "+proj=longlat +pm=180", 640, 480, (125.0, -35.0, 175.0, 3.0))
|
|
1816
|
+
img1 = Image.new("RGBA", (640, 480))
|
|
1817
|
+
img2 = Image.new("RGBA", (640, 480))
|
|
1818
|
+
img3 = Image.new("RGBA", (640, 480))
|
|
1819
|
+
|
|
1820
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
1821
|
+
cw.add_coastlines(img1, area_def1, resolution="l", level=4)
|
|
1822
|
+
cw.add_coastlines(img2, area_def2, resolution="l", level=4)
|
|
1823
|
+
cw.add_coastlines(img3, area_def3, resolution="l", level=4)
|
|
1824
|
+
|
|
1825
|
+
# with a prime meridian shift and extents shift, the images should be the same
|
|
1826
|
+
np.testing.assert_allclose(np.array(img1), np.array(img3))
|
|
1827
|
+
# with only a prime meridian shift and same extents, the images should be completely different
|
|
1828
|
+
_assert_all_notclose(np.array(img1), np.array(img2))
|
|
1829
|
+
# with only an extents change, the images should be completely different
|
|
1830
|
+
_assert_all_notclose(np.array(img2), np.array(img3))
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
def _assert_all_notclose(*args, **kwargs):
|
|
1834
|
+
with pytest.raises(AssertionError):
|
|
1835
|
+
np.testing.assert_allclose(*args, **kwargs)
|
|
1836
|
+
|
|
1837
|
+
|
|
1838
|
+
class FakeAreaDef:
|
|
1839
|
+
"""A fake area definition object."""
|
|
1840
|
+
|
|
1841
|
+
def __init__(self, proj4_string, area_extent, x_size, y_size):
|
|
1842
|
+
self.proj_str = self.proj_dict = proj4_string
|
|
1843
|
+
self.crs = CRS.from_user_input(proj4_string)
|
|
1844
|
+
self.area_extent = area_extent
|
|
1845
|
+
self.width = x_size
|
|
1846
|
+
self.height = y_size
|
|
1847
|
+
self.area_id = "fakearea"
|
|
1848
|
+
|
|
616
1849
|
|
|
1850
|
+
class TestFromConfig:
|
|
1851
|
+
"""Test burning overlays from a config file."""
|
|
617
1852
|
|
|
618
|
-
def
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
mysuite.addTest(loader.loadTestsFromTestCase(TestPIL))
|
|
622
|
-
# mysuite.addTest(loader.loadTestsFromTestCase(TestPILAGG))
|
|
1853
|
+
def test_foreground(self):
|
|
1854
|
+
"""Test generating a transparent foreground."""
|
|
1855
|
+
from pycoast import ContourWriterPIL
|
|
623
1856
|
|
|
624
|
-
|
|
1857
|
+
euro_img = Image.open(os.path.join(LOCAL_DIR, "contours_europe_alpha.png"))
|
|
1858
|
+
euro_data = np.array(euro_img)
|
|
1859
|
+
|
|
1860
|
+
# img = Image.new('RGB', (640, 480))
|
|
1861
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
1862
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
1863
|
+
area_def = FakeAreaDef(proj4_string, area_extent, 640, 480)
|
|
1864
|
+
cw = ContourWriterPIL(gshhs_root_dir)
|
|
1865
|
+
config_file = os.path.join(LOCAL_DIR, "test_data", "test_config.ini")
|
|
1866
|
+
img = cw.add_overlay_from_config(config_file, area_def)
|
|
1867
|
+
|
|
1868
|
+
res = np.array(img)
|
|
1869
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1870
|
+
|
|
1871
|
+
overlays = {
|
|
1872
|
+
"coasts": {"level": [1, 2, 3, 4], "resolution": "l"},
|
|
1873
|
+
"borders": {"outline": (255, 0, 0), "resolution": "c"},
|
|
1874
|
+
"rivers": {"outline": "blue", "resolution": "c", "level": 5},
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1878
|
+
res = np.array(img)
|
|
1879
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1880
|
+
|
|
1881
|
+
def test_cache_generation_reuse(self, tmpdir):
|
|
1882
|
+
"""Test generating a transparent foreground and cache it."""
|
|
1883
|
+
from pycoast import ContourWriterPIL
|
|
1884
|
+
|
|
1885
|
+
euro_img = Image.open(os.path.join(LOCAL_DIR, "contours_europe_alpha.png"))
|
|
1886
|
+
euro_data = np.array(euro_img)
|
|
1887
|
+
|
|
1888
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
1889
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
1890
|
+
area_def = FakeAreaDef(proj4_string, area_extent, 640, 480)
|
|
1891
|
+
cw = ContourWriterPIL(gshhs_root_dir)
|
|
1892
|
+
|
|
1893
|
+
overlays = {
|
|
1894
|
+
"cache": {"file": os.path.join(tmpdir, "pycoast_cache")},
|
|
1895
|
+
"coasts": {"level": 4, "resolution": "l"},
|
|
1896
|
+
"borders": {"outline": (255, 0, 0), "resolution": "c"},
|
|
1897
|
+
"rivers": {"outline": "blue", "resolution": "c", "level": 5},
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
# Create the original cache file
|
|
1901
|
+
img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1902
|
+
res = np.array(img)
|
|
1903
|
+
img.close()
|
|
1904
|
+
cache_glob = glob(os.path.join(tmpdir, "pycoast_cache_*.png"))
|
|
1905
|
+
assert len(cache_glob) == 1
|
|
1906
|
+
cache_filename = cache_glob[0]
|
|
1907
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1908
|
+
assert os.path.isfile(cache_filename)
|
|
1909
|
+
mtime = os.path.getmtime(cache_filename)
|
|
1910
|
+
|
|
1911
|
+
# Reuse the generated cache file
|
|
1912
|
+
img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1913
|
+
res = np.array(img)
|
|
1914
|
+
img.close()
|
|
1915
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1916
|
+
assert os.path.isfile(cache_filename)
|
|
1917
|
+
assert os.path.getmtime(cache_filename) == mtime
|
|
1918
|
+
|
|
1919
|
+
# Regenerate cache file
|
|
1920
|
+
current_time = time.time()
|
|
1921
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def, current_time)
|
|
1922
|
+
fg_img.close()
|
|
1923
|
+
mtime = os.path.getmtime(cache_filename)
|
|
1924
|
+
assert mtime > current_time
|
|
1925
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1926
|
+
|
|
1927
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def, current_time)
|
|
1928
|
+
fg_img.close()
|
|
1929
|
+
assert os.path.getmtime(cache_filename) == mtime
|
|
1930
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1931
|
+
overlays["cache"]["regenerate"] = True
|
|
1932
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1933
|
+
fg_img.close()
|
|
1934
|
+
|
|
1935
|
+
assert os.path.getmtime(cache_filename) != mtime
|
|
1936
|
+
assert fft_metric(euro_data, res), "Writing of contours failed"
|
|
1937
|
+
|
|
1938
|
+
overlays.pop("cache")
|
|
1939
|
+
overlays["grid"] = {
|
|
1940
|
+
"outline": (255, 255, 255),
|
|
1941
|
+
"outline_opacity": 175,
|
|
1942
|
+
"minor_outline": (200, 200, 200),
|
|
1943
|
+
"minor_outline_opacity": 127,
|
|
1944
|
+
"width": 1.0,
|
|
1945
|
+
"minor_width": 0.5,
|
|
1946
|
+
"minor_is_tick": True,
|
|
1947
|
+
"write_text": True,
|
|
1948
|
+
"lat_placement": "lr",
|
|
1949
|
+
"lon_placement": "b",
|
|
1950
|
+
}
|
|
1951
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1952
|
+
fg_img.close()
|
|
1953
|
+
os.remove(cache_filename)
|
|
1954
|
+
|
|
1955
|
+
def test_caching_with_param_changes(self, tmpdir):
|
|
1956
|
+
"""Testing caching when changing parameters."""
|
|
1957
|
+
from pycoast import ContourWriterPIL
|
|
1958
|
+
|
|
1959
|
+
proj4_string = "+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84"
|
|
1960
|
+
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
|
|
1961
|
+
area_def = FakeAreaDef(proj4_string, area_extent, 640, 480)
|
|
1962
|
+
cw = ContourWriterPIL(gshhs_root_dir)
|
|
1963
|
+
|
|
1964
|
+
font = ImageFont.truetype(font_path)
|
|
1965
|
+
overlays = {
|
|
1966
|
+
"cache": {"file": os.path.join(tmpdir, "pycoast_cache")},
|
|
1967
|
+
"grid": {"font": font},
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
# Create the original cache file
|
|
1971
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1972
|
+
fg_img.close()
|
|
1973
|
+
cache_glob = glob(os.path.join(tmpdir, "pycoast_cache_*.png"))
|
|
1974
|
+
assert len(cache_glob) == 1
|
|
1975
|
+
cache_filename = cache_glob[0]
|
|
1976
|
+
assert os.path.isfile(cache_filename)
|
|
1977
|
+
mtime = os.path.getmtime(cache_filename)
|
|
1978
|
+
|
|
1979
|
+
# Reuse the generated cache file
|
|
1980
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1981
|
+
fg_img.close()
|
|
1982
|
+
cache_glob = glob(os.path.join(tmpdir, "pycoast_cache_*.png"))
|
|
1983
|
+
assert len(cache_glob) == 1
|
|
1984
|
+
assert os.path.isfile(cache_filename)
|
|
1985
|
+
assert os.path.getmtime(cache_filename) == mtime
|
|
1986
|
+
|
|
1987
|
+
# Remove the font option, should produce the same result
|
|
1988
|
+
# font is not considered when caching
|
|
1989
|
+
del overlays["grid"]["font"]
|
|
1990
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def)
|
|
1991
|
+
fg_img.close()
|
|
1992
|
+
cache_glob = glob(os.path.join(tmpdir, "pycoast_cache_*.png"))
|
|
1993
|
+
assert len(cache_glob) == 1
|
|
1994
|
+
assert os.path.isfile(cache_filename)
|
|
1995
|
+
assert os.path.getmtime(cache_filename) == mtime
|
|
1996
|
+
|
|
1997
|
+
# Changing a parameter should create a new cache file
|
|
1998
|
+
overlays = {
|
|
1999
|
+
"cache": {"file": os.path.join(tmpdir, "pycoast_cache")},
|
|
2000
|
+
"grid": {"width": 2.0},
|
|
2001
|
+
}
|
|
2002
|
+
fg_img = cw.add_overlay_from_dict(overlays, area_def)
|
|
2003
|
+
fg_img.close()
|
|
2004
|
+
cache_glob = glob(os.path.join(tmpdir, "pycoast_cache_*.png"))
|
|
2005
|
+
assert len(cache_glob) == 2
|
|
2006
|
+
assert os.path.isfile(cache_filename)
|
|
2007
|
+
new_cache_filename = cache_glob[0] if cache_glob[0] != cache_filename else cache_glob[1]
|
|
2008
|
+
# original cache file should be unchanged
|
|
2009
|
+
assert os.path.getmtime(cache_filename) == mtime
|
|
2010
|
+
# new cache file should be...new
|
|
2011
|
+
assert os.path.getmtime(new_cache_filename) != mtime
|
|
2012
|
+
|
|
2013
|
+
@pytest.mark.parametrize("background_mode", ["RGB", "RGBA"])
|
|
2014
|
+
@pytest.mark.parametrize("include_background_pattern", [False, True])
|
|
2015
|
+
@pytest.mark.parametrize("upper_right_opacity", [32, 127, 255])
|
|
2016
|
+
def test_cache_nocache_consistency(
|
|
2017
|
+
self, tmp_path, include_background_pattern, background_mode, upper_right_opacity
|
|
2018
|
+
):
|
|
2019
|
+
"""Test that an image generated with an image looks the same when using a cached foreground."""
|
|
2020
|
+
from pycoast import ContourWriterAGG
|
|
2021
|
+
|
|
2022
|
+
proj4_string = "+proj=longlat +ellps=WGS84"
|
|
2023
|
+
area_extent = (-10.0, -10.0, 10.0, 10.0)
|
|
2024
|
+
area_def = FakeAreaDef(proj4_string, area_extent, 200, 200)
|
|
2025
|
+
cw = ContourWriterAGG(gshhs_root_dir)
|
|
2026
|
+
|
|
2027
|
+
# create test shapefiles
|
|
2028
|
+
test_shape_filename1 = tmp_path / "test_shapes1"
|
|
2029
|
+
_create_polygon_shapefile(test_shape_filename1, [[[-10.0, 10.0], [-5.0, 10.0], [-5.0, 5.0], [-10.0, 5.0]]])
|
|
2030
|
+
test_shape_filename2 = tmp_path / "test_shapes2"
|
|
2031
|
+
_create_polygon_shapefile(test_shape_filename2, [[[5.0, 10.0], [10.0, 10.0], [10.0, 5.0], [5.0, 5.0]]])
|
|
2032
|
+
|
|
2033
|
+
overlays = {
|
|
2034
|
+
"cache": {"file": os.path.join(tmp_path, "pycoast_cache")},
|
|
2035
|
+
"shapefiles": [
|
|
2036
|
+
{
|
|
2037
|
+
"filename": str(test_shape_filename1),
|
|
2038
|
+
"fill": (0, 255, 0),
|
|
2039
|
+
"outline": (255, 255, 255),
|
|
2040
|
+
"fill_opacity": 255,
|
|
2041
|
+
},
|
|
2042
|
+
{
|
|
2043
|
+
"filename": str(test_shape_filename2),
|
|
2044
|
+
"fill": (0, 255, 0),
|
|
2045
|
+
"outline": (255, 255, 0),
|
|
2046
|
+
"fill_opacity": upper_right_opacity,
|
|
2047
|
+
},
|
|
2048
|
+
],
|
|
2049
|
+
}
|
|
625
2050
|
|
|
626
|
-
|
|
627
|
-
|
|
2051
|
+
# Create the original cache file
|
|
2052
|
+
background_img1 = _create_background_image(include_background_pattern, background_mode)
|
|
2053
|
+
cached_image1 = cw.add_overlay_from_dict(overlays, area_def, background=background_img1)
|
|
2054
|
+
|
|
2055
|
+
# Reuse the generated cache file
|
|
2056
|
+
background_img2 = _create_background_image(include_background_pattern, background_mode)
|
|
2057
|
+
cached_image2 = cw.add_overlay_from_dict(overlays, area_def, background=background_img2)
|
|
2058
|
+
|
|
2059
|
+
# Create without cache
|
|
2060
|
+
overlays.pop("cache")
|
|
2061
|
+
background_img3 = _create_background_image(include_background_pattern, background_mode)
|
|
2062
|
+
cw.add_overlay_from_dict(overlays, area_def, background=background_img3)
|
|
2063
|
+
|
|
2064
|
+
# Manually (no dict, no cache)
|
|
2065
|
+
background_img4 = _create_background_image(include_background_pattern, background_mode)
|
|
2066
|
+
for shape_params in overlays["shapefiles"]:
|
|
2067
|
+
cw.add_shapefile_shapes(background_img4, area_def, **shape_params)
|
|
2068
|
+
|
|
2069
|
+
# two transparent overlay images
|
|
2070
|
+
np.testing.assert_allclose(np.array(cached_image1), np.array(cached_image2), atol=0)
|
|
2071
|
+
# cached overlay applied to background image should always be equal
|
|
2072
|
+
np.testing.assert_allclose(np.array(background_img1), np.array(background_img2), atol=0)
|
|
2073
|
+
# cached overlay applied to background image and regenerated overlay on background image should be equal
|
|
2074
|
+
# but due to floating point differences they are off by a little bit
|
|
2075
|
+
np.testing.assert_allclose(
|
|
2076
|
+
np.array(background_img1, dtype=np.float32), np.array(background_img3, dtype=np.float32), atol=1
|
|
2077
|
+
)
|
|
2078
|
+
# no cache version and manual version should be the same
|
|
2079
|
+
np.testing.assert_allclose(np.array(background_img3), np.array(background_img4), atol=0)
|
|
2080
|
+
|
|
2081
|
+
@pytest.mark.parametrize(
|
|
2082
|
+
("crs_input", "extents", "size", "exp_resolution"),
|
|
2083
|
+
[
|
|
2084
|
+
(
|
|
2085
|
+
"+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84",
|
|
2086
|
+
(-3363403.31, -2291879.85, 2630596.69, 2203620.1),
|
|
2087
|
+
(640, 480),
|
|
2088
|
+
"l",
|
|
2089
|
+
),
|
|
2090
|
+
(
|
|
2091
|
+
"+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84",
|
|
2092
|
+
(-3363403.31, -2291879.85, 2630596.69, 2203620.1),
|
|
2093
|
+
(6400, 4800),
|
|
2094
|
+
"h",
|
|
2095
|
+
),
|
|
2096
|
+
("+proj=longlat +ellps=WGS84", (-45.0, -35.0, 5.0, 3.0), (640, 480), "l"),
|
|
2097
|
+
("+proj=longlat +pm=180 +ellps=WGS84", (-45.0, -35.0, 5.0, 3.0), (640, 480), "l"),
|
|
2098
|
+
],
|
|
2099
|
+
)
|
|
2100
|
+
def test_get_resolution(self, crs_input, extents, size, exp_resolution):
|
|
2101
|
+
"""Get the automagical resolution computation."""
|
|
2102
|
+
from pycoast import get_resolution_from_area
|
|
2103
|
+
|
|
2104
|
+
crs = CRS.from_user_input(crs_input)
|
|
2105
|
+
area_def = FakeAreaDef(crs, extents, *size)
|
|
2106
|
+
assert get_resolution_from_area(area_def) == exp_resolution
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
def _create_polygon_shapefile(fn: pathlib.Path, polygon_coords: list) -> None:
|
|
2110
|
+
with shapefile.Writer(fn) as test_shapefile:
|
|
2111
|
+
test_shapefile.field("name", "C")
|
|
2112
|
+
test_shapefile.poly(polygon_coords)
|
|
2113
|
+
test_shapefile.record("test")
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
def _create_background_image(add_pattern: bool, background_mode: str) -> Image:
|
|
2117
|
+
num_bands = len(background_mode)
|
|
2118
|
+
img_data = np.zeros((200, 200, num_bands), dtype=np.uint8)
|
|
2119
|
+
if background_mode[-1] == "A":
|
|
2120
|
+
img_data[..., -1] = 255
|
|
2121
|
+
if add_pattern:
|
|
2122
|
+
img_data[6:30, 6:30, 0] = 127
|
|
2123
|
+
img_data[6:30, -30:-6, 0] = 127
|
|
2124
|
+
return Image.fromarray(img_data, mode=background_mode)
|