Skip to content

Commit 05e6228

Browse files
committed
Fixed and improved error detection in explre/protected_areas
1 parent 69a07f9 commit 05e6228

File tree

2 files changed

+91
-20
lines changed

2 files changed

+91
-20
lines changed
10.3 KB
Binary file not shown.

themes/explore/topics/protected_areas.lua

Lines changed: 91 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ themepark:add_table({
2525
{ column = 'operator_wikidata', type = 'text' },
2626
{ column = 'related_law', type = 'text' },
2727
{ column = 'related_law_url', type = 'text' },
28-
{ column = 'iucn', type = 'text' }, -- tag "ref:IUCN"
2928
{ column = 'iucn_level', type = 'text' }, -- tag "iucn_level"
29+
{ column = 'iucn', type = 'text' }, -- IUCN category from iucn_level or protect_class
3030
{ column = 'wdpa', type = 'int' }, -- WDPA
3131
{ column = 'capad_pa_id', type = 'text' }, -- Collaborative Australian Protected Areas Database (CAPAD)
3232
{ column = 'dtp_id', type = 'text' }, -- DIGITIZE THE PLANET
@@ -37,58 +37,129 @@ themepark:add_table({
3737
name = 'protected_areas_errors',
3838
ids_type = 'area',
3939
geom = 'multipolygon',
40-
columns = {
41-
{ column = 'errormsg', type = 'text', not_null = true },
40+
columns = themepark:columns({
41+
{ column = 'ecode', type = 'text', not_null = true },
42+
{ column = 'emsg', type = 'text', not_null = true },
4243
{ column = 'value', type = 'text' },
43-
}
44+
})
4445
})
4546

47+
-- ---------------------------------------------------------------------------
48+
4649
local get_qcode = function(wd)
4750
if wd and wd:match('^Q%d+$') then
4851
return wd
4952
end
5053
return nil
5154
end
5255

56+
-- See https://en.wikipedia.org/wiki/IUCN_protected_area_categories
57+
local iucn_mapping = {
58+
-- these are the official levels
59+
['IA'] = 'IA', -- strict nature reserve
60+
['IB'] = 'IB', -- wilderness area
61+
['II'] = 'II', -- national park
62+
['III'] = 'III', -- natural monument or feature
63+
['IV'] = 'IV', -- habitat or species management area
64+
['V'] = 'V', -- protected landscape or seascape
65+
['VI'] = 'VI', -- protected area with sustainable use of natural resources
66+
67+
-- these are different forms of the official levels
68+
['Ia'] = 'IA',
69+
['Ib'] = 'IB',
70+
['1a'] = 'IA',
71+
['1b'] = 'IB',
72+
['2'] = 'II',
73+
['3'] = 'III',
74+
['4'] = 'IV',
75+
['5'] = 'V',
76+
['6'] = 'VI',
77+
}
78+
79+
local function valid_protect_class(pc)
80+
if pc == '1a' or pc == '1b' then
81+
return true
82+
end
83+
return pc:match('^%d%d?$')
84+
end
85+
86+
-- ---------------------------------------------------------------------------
87+
88+
local error_messages = {
89+
dtp_id = 'invalid dtp_id (not a UUID)',
90+
iucn_level = 'invalid iucn_level',
91+
iucn_level_protect_class_mismatch = 'iucn_level tag does not match protect_class tag',
92+
operator_wikidata = 'invalid Q-item code for operator_wikidata tag',
93+
protect_class = 'invalid protect_class (allowed: 1a, 1b, 1-99)',
94+
ref_wdpa = 'invalid ref:WDPA tag (not an integer)',
95+
wikidata = 'invalid Q-item code for wikidata tag',
96+
}
97+
98+
local function add_error(ecode, value, geom, tags)
99+
themepark:insert('protected_areas_errors', {
100+
ecode = ecode,
101+
emsg = error_messages[ecode],
102+
value = value,
103+
geom = geom,
104+
}, tags)
105+
end
106+
107+
-- ---------------------------------------------------------------------------
108+
53109
themepark:add_proc('area', function(object, data)
54110
local t = object.tags
55111
if t.boundary == 'protected_area'
56112
or t.boundary == 'national_park' or t.boundary == 'water_protection_area'
57113
or t.leisure == 'nature_reserve' or t.protected_area then
58114

115+
local geom = object:as_area()
116+
59117
-- Check that wikidata tags contain syntactically valid Q codes
60118
-- https://www.wikidata.org/wiki/{wikidata_code}
61119
local wikidata_code = get_qcode(t.wikidata)
62120
local operator_wikidata_code = get_qcode(t.operator_wikidata)
63121

64122
if t.wikidata ~= wikidata_code then
65-
themepark:insert('protected_areas_errors', {
66-
errormsg = 'invalid Q-item code for wikidata tag',
67-
value = t.wikidata
68-
}, t)
123+
add_error('wikidata', t.wikidata, geom, t)
69124
end
70125
if t.operator_wikidata ~= operator_wikidata_code then
71-
themepark:insert('protected_areas_errors', {
72-
errormsg = 'invalid Q-item code for operator_wikidata tag',
73-
value = t.operator_wikidata
74-
}, t)
126+
add_error('operator_wikidata', t.operator_wikidata, geom, t)
127+
end
128+
129+
local iucn = iucn_mapping[t.iucn_level]
130+
if t.iucn_level and iucn == nil then
131+
add_error('iucn_level', t.iucn_level, geom, t)
132+
end
133+
134+
if t.protect_class and not valid_protect_class(t.protect_class) then
135+
add_error('protect_class', t.protect_class, geom, t)
136+
end
137+
138+
if iucn then
139+
if iucn_mapping[t.protect_class] and iucn ~= iucn_mapping[t.protect_class] then
140+
add_error('iucn_level_protect_class_mismatch', t.iucn_level .. ' <> ' .. t.protect_class, geom, t)
141+
end
142+
else
143+
iucn = iucn_mapping[t.protect_class]
75144
end
76145

77146
-- WDPA is always an integer
78147
-- https://www.protectedplanet.net/{wdpa}
79148
local wdpa = t['ref:WDPA']
80-
if wdpa and wdpa:match('^%d+$') then
81-
wdpa = tonumber(wdpa)
82-
else
83-
themepark:insert('protected_areas_errors', { errormsg = 'not a number in ref:WDPA tag', value = wdpa }, t)
84-
wdpa = nil
149+
if wdpa then
150+
if wdpa:match('^%d+$') then
151+
wdpa = tonumber(wdpa)
152+
else
153+
add_error('ref_wdpa', wdpa, geom, t)
154+
wdpa = nil
155+
end
85156
end
86157

87158
-- Digitize The Planet uses UUIDs
88159
-- https://content.digitizetheplanet.org/de/rules/show_protectedarea/{dtp_id}
89160
local dtp_id = t.dtp_id
90161
if dtp_id and not dtp_id:match('^[0-9a-f-]+$') then
91-
themepark:insert('protected_areas_errors', { errormsg = 'not a UUID in dtp_id tag', value = dtp_id }, t)
162+
add_error('dtp_id', dtp_id, geom, t)
92163
end
93164

94165
local a = {
@@ -106,12 +177,12 @@ themepark:add_proc('area', function(object, data)
106177
operator_wikidata = operator_wikidata_code,
107178
related_law = t.related_law,
108179
related_law_url = t['related_law:url'],
109-
iucn = t['ref:IUCN'],
110180
iucn_level = t.iucn_level,
181+
iucn = iucn,
111182
wdpa = wdpa,
112183
capad_pa_id = t['ref:capad:pa_id'],
113184
dtp_id = dtp_id,
114-
geom = object:as_area(),
185+
geom = geom,
115186
}
116187

117188
themepark.themes.core.add_name(a, object)

0 commit comments

Comments
 (0)