Skip to content

Commit ec1b4b4

Browse files
author
Rub21
committed
Fixing functions to update geom, centroid and bbox - admin2
1 parent a8a5d26 commit ec1b4b4

File tree

1 file changed

+114
-145
lines changed

1 file changed

+114
-145
lines changed
Lines changed: 114 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import sys
2-
import os
31
import csv
42
from django.core.management.base import BaseCommand, CommandError
53
from django.contrib.gis.gdal import DataSource
64
from django.contrib.gis.geos import GEOSGeometry
75
from django.contrib.gis.geos import MultiPolygon
86
from django.core.exceptions import ObjectDoesNotExist
7+
from django.db import IntegrityError
98
from django.db import transaction
109
from api.models import Country
1110
from api.models import District
@@ -53,150 +52,107 @@ def add_arguments(self, parser):
5352

5453
@transaction.atomic
5554
def handle(self, *args, **options):
56-
filename = options['filename'][0]
57-
# a dict to hold all the admin2 that needs to be manually imported
58-
import_missing = {}
59-
if options['import_missing']:
60-
import_file = csv.DictReader(open(options['import_missing']), fieldnames=['code', 'name'])
61-
next(import_file)
62-
for row in import_file:
63-
code = row['code']
64-
name = row['name']
65-
import_missing[code] = {
66-
'code': code,
67-
'name': name
68-
}
69-
print('will import these codes', import_missing.keys())
70-
else:
71-
# if no filename is specified, open one to write missing code and names
72-
missing_filename="missing-admin2.txt"
73-
print(f'will write missing admin2 codes to {missing_filename}')
74-
missing_file = csv.DictWriter(open(missing_filename, 'w'), fieldnames=['code', 'name'])
75-
missing_file.writeheader()
76-
77-
try:
78-
data = DataSource(filename)
79-
except:
80-
raise CommandError('Could not open file')
81-
82-
# loop through each feature in the shapefile
83-
for feature in data[0]:
84-
code = feature.get('code')
85-
name = feature.get('name')
86-
geom_wkt = feature.geom.wkt
87-
geom = GEOSGeometry(geom_wkt, srid=4326)
88-
if (geom.geom_type == 'Polygon'):
89-
geom = MultiPolygon(geom)
90-
91-
centroid = geom.centroid.wkt
92-
bbox = geom.envelope.wkt
93-
# import all shapes for admin2
94-
if options['import_all']:
95-
self.add_admin2(options, 'all', feature, geom, centroid, bbox)
55+
filename = options["filename"][0]
56+
# a dict to hold all the admin2 that needs to be manually imported
57+
import_missing = {}
58+
if options["import_missing"]:
59+
import_file = csv.DictReader(open(options["import_missing"]), fieldnames=["code", "name"])
60+
next(import_file)
61+
for row in import_file:
62+
code = row["code"]
63+
name = row["name"]
64+
import_missing[code] = {"code": code, "name": name}
65+
print("will import these codes", import_missing.keys())
9666
else:
97-
admin2_objects = Admin2.objects.filter(code=code)
98-
if len(admin2_objects) == 0:
99-
if options['import_missing']:
100-
# if it doesn't exist, add it
101-
self.add_admin2(options, import_missing, feature, geom, centroid, bbox)
102-
else:
103-
missing_file.writerow({'code': code, 'name': name})
67+
# if no filename is specified, open one to write missing code and names
68+
missing_filename = "missing-admin2.txt"
69+
print(f"will write missing admin2 codes to {missing_filename}")
70+
missing_file = csv.DictWriter(open(missing_filename, "w"), fieldnames=["code", "name"])
71+
missing_file.writeheader()
10472

105-
# if there are more than one admin2 with the same code, filter also using name
106-
if len(admin2_objects) > 1:
107-
admins2_names = Admin2.objects.filter(code=code, name__icontains=name)
108-
# if we get a match, update geometry. otherwise consider this as missing because it's possible the names aren't matching.
109-
if len(admins2_names):
110-
# update geom, centroid and bbox
111-
d = admins2_names[0]
112-
if options['update_geom']:
113-
self.update_geom(d, geom)
114-
if options['update_centroid']:
115-
d.centroid = centroid
116-
if options['update_bbox']:
117-
d.bbox = bbox
118-
d.save()
73+
try:
74+
data = DataSource(filename)
75+
except:
76+
raise CommandError("Could not open file")
77+
78+
# loop through each feature in the shapefile
79+
for feature in data[0]:
80+
code = feature.get("code")
81+
name = feature.get("name")
82+
geom_wkt = feature.geom.wkt
83+
geom = GEOSGeometry(geom_wkt, srid=4326)
84+
if geom.geom_type == "Polygon":
85+
geom = MultiPolygon(geom)
86+
87+
centroid = geom.centroid.wkt
88+
bbox = geom.envelope.wkt
89+
# import all shapes for admin2
90+
if options["import_all"]:
91+
self.add_admin2(options, "all", feature, geom, centroid, bbox)
11992
else:
120-
if options['import_missing']:
121-
# if it doesn't exist, add it
122-
self.add_admin2(options, import_missing, feature, geom, centroid, bbox)
123-
else:
124-
missing_file.writerow({'code': code, 'name': name})
125-
126-
127-
if len(admin2_objects) == 1:
128-
d = admin2_objects[0]
129-
if options['update_geom']:
130-
self.update_geom(d, geom)
131-
if options['update_centroid']:
132-
d.centroid = centroid
133-
if options['update_bbox']:
134-
d.bbox = bbox
135-
d.save()
136-
137-
# if code == 'N.A':
138-
# admin2 = Admin2.objects.filter(name__icontains=name)
139-
# if len(admin2):
140-
# d = admin2[0]
141-
# if options['update_geom']:
142-
# self.update_geom(d, geom)
143-
# if options['update_centroid']:
144-
# d.centroid = centroid
145-
# if options['update_bbox']:
146-
# d.bbox = bbox
147-
# d.save()
148-
# else:
149-
# if options['import_missing']:
150-
# self.add_admin2(options, import_missing, feature, geom, centroid, bbox)
151-
# else:
152-
# missing_file.writerow({'code': code, 'name': name})
153-
154-
# if code == 'f':
155-
# admin2 = Admin2.objects.filter(name__icontains=name)
156-
# if not len(admin2):
157-
# if options['import_missing']:
158-
# self.add_admin2(options, import_missing, feature, geom, centroid, bbox)
159-
# else:
160-
# missing_file.writerow({'code': code, 'name': name})
161-
print('done!')
162-
93+
admin2_objects = Admin2.objects.filter(code=code)
94+
if len(admin2_objects) == 0:
95+
if options["import_missing"]:
96+
# if it doesn't exist, add it
97+
self.add_admin2(options, import_missing, feature, geom, centroid, bbox)
98+
else:
99+
missing_file.writerow({"code": code, "name": name})
100+
101+
# if there are more than one admin2 with the same code, filter also using name
102+
if len(admin2_objects) > 1:
103+
admins2_names = Admin2.objects.filter(code=code, name__icontains=name)
104+
# if we get a match, update geometry. otherwise consider this as missing because it's possible the names aren't matching.
105+
if len(admins2_names):
106+
# update geom, centroid and bbox
107+
self.update_admin2_columns(options, admins2_names[0], geom, centroid, bbox)
108+
else:
109+
if options["import_missing"]:
110+
# if it doesn't exist, add it
111+
self.add_admin2(options, import_missing, feature, geom, centroid, bbox)
112+
else:
113+
missing_file.writerow({"code": code, "name": name})
114+
if len(admin2_objects) == 1:
115+
self.update_admin2_columns(options, admin2_objects[0], geom, centroid, bbox)
116+
print("done!")
163117

118+
@transaction.atomic
164119
def add_admin2(self, options, import_missing, feature, geom, centroid, bbox):
165-
code = feature.get('code') or 'N.A'
166-
name = feature.get('name')
167-
admin2 = Admin2()
168-
admin2.code = code
169-
admin2.name = name
170-
admin2.centroid = centroid
171-
admin2.bbox = bbox
172-
try:
120+
code = feature.get("code") or "N.A"
121+
name = feature.get("name")
122+
admin2 = Admin2()
123+
admin2.code = code
124+
admin2.name = name
125+
admin2.centroid = centroid
126+
admin2.bbox = bbox
127+
country_iso2 = options["country_iso2"]
173128
# find district_id based on centroid of admin2 and country.
174-
admin1_id = self.find_district_id(centroid, options['country_iso2'])
175-
if admin1_id is None:
176-
print('country does not exist', "af")
177-
pass
178-
else:
179-
admin2.admin1_id = admin1_id
180-
except ObjectDoesNotExist:
181-
print('country does not exist', "af")
182-
pass
183-
184-
if (import_missing == 'all') or (code in import_missing.keys()):
185-
print('importing', admin2.name)
186-
admin2.save()
187-
if (options['update_geom']):
188-
self.update_geom(admin2, geom)
129+
try:
130+
admin2.admin1_id = self.find_district_id(centroid, country_iso2)
131+
except ObjectDoesNotExist:
132+
print(f"Country({country_iso2}) or admin 1 does not found for - admin2: {name}")
133+
pass
134+
135+
# save data
136+
if admin2.admin1_id is not None and ((import_missing == "all") or (code in import_missing.keys())):
137+
try:
138+
admin2.save()
139+
print("importing", admin2.name)
140+
if options["update_geom"]:
141+
self.update_geom(admin2, geom)
142+
except IntegrityError as e:
143+
print(f"Duplicate object {admin2.name}")
144+
pass
189145

190146
def update_geom(self, admin2, geom):
191147
try:
192-
Admin2Geom = Admin2Geoms.objects.get(admin2=admin2)
193-
Admin2Geom.geom = geom
194-
Admin2Geom.save()
148+
Admin2Geom = Admin2Geoms.objects.get(admin2=admin2)
149+
Admin2Geom.geom = geom
150+
Admin2Geom.save()
195151
except ObjectDoesNotExist:
196-
Admin2Geom = DistrictGeoms()
197-
Admin2Geom.admin2 = admin2
198-
Admin2Geom.geom = geom
199-
Admin2Geom.save()
152+
Admin2Geom = Admin2Geoms()
153+
Admin2Geom.admin2 = admin2
154+
Admin2Geom.geom = geom
155+
Admin2Geom.save()
200156

201157
def find_district_id(self, centroid, country_iso2):
202158
"""Find district_id for admin2, according to the point with in the district polygon.
@@ -206,12 +162,25 @@ def find_district_id(self, centroid, country_iso2):
206162
"""
207163
admin1_id = None
208164
country_id = Country.objects.get(iso=country_iso2)
209-
districts = District.objects.filter(country_id=country_id)
210-
districts_ids = [d.id for d in districts]
211-
districts_geoms = DistrictGeoms.objects.filter(district_id__in=districts_ids)
212-
centroid_geom = GEOSGeometry(centroid, srid=4326)
213-
for district_geom in districts_geoms:
214-
if centroid_geom.within(district_geom.geom):
215-
admin1_id = district_geom.district_id
216-
break
217-
return admin1_id
165+
if country_id is not None:
166+
districts = District.objects.filter(country_id=country_id)
167+
districts_ids = [d.id for d in districts]
168+
districts_geoms = DistrictGeoms.objects.filter(district_id__in=districts_ids)
169+
centroid_geom = GEOSGeometry(centroid, srid=4326)
170+
for district_geom in districts_geoms:
171+
if centroid_geom.within(district_geom.geom):
172+
admin1_id = district_geom.district_id
173+
break
174+
return admin1_id
175+
176+
def update_admin2_columns(self, options, admin2, geom, centroid, bbox):
177+
if options["update_geom"]:
178+
print(f"Update geom for {admin2.name}")
179+
self.update_geom(admin2, geom)
180+
if options["update_centroid"]:
181+
print(f"Update centroid for {admin2.name}")
182+
admin2.centroid = centroid
183+
if options["update_bbox"]:
184+
print(f"Update bbox for {admin2.name}")
185+
admin2.bbox = bbox
186+
admin2.save()

0 commit comments

Comments
 (0)