Skip to content

Commit 21f5add

Browse files
ajparsonsdracos
authored andcommitted
[UK] New import command for post-2011 LSOAs/DZ/SOA
1 parent 187222d commit 21f5add

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# This script is used to import boundary polygons and other information
2+
# from shapefiles representing areas of census geography
3+
4+
# Run as: ./manage.py mapit_UK_import_soa_2011 shapefile.shp --type=lsoa
5+
# --commit
6+
7+
from django.core.management.base import LabelCommand
8+
from django.contrib.gis.gdal import DataSource
9+
from mapit.models import Area, Generation, Country, Type, NameType, CodeType
10+
from django.conf import settings
11+
from enum import Enum
12+
from mapit.management.command_utils import save_polygons
13+
14+
15+
class GeographyType(Enum):
16+
"""
17+
allowed geographic imports
18+
"""
19+
lsoa = "lsoa"
20+
msoa = "msoa"
21+
soa = "soa"
22+
dz = "dz"
23+
lz = "lz"
24+
25+
def __str__(self):
26+
return self.value
27+
28+
29+
class Command(LabelCommand):
30+
help = 'Creates Super Output Area boundaries from ONS/Scot Gov/OSNI shapefiles'
31+
label = '<ONS SOA shapefile>'
32+
33+
def add_arguments(self, parser):
34+
super(Command, self).add_arguments(parser)
35+
parser.add_argument('--commit', action='store_true',
36+
dest='commit', help='Actually update the database')
37+
parser.add_argument('--type', dest='file_type', help="options: lsoa, msoa, soa, dz, lz",
38+
type=GeographyType, choices=list(GeographyType)
39+
)
40+
parser.add_argument('--generalized', action='store_true',
41+
dest='generalized', help='Is shape generalised?')
42+
43+
def handle_label(self, filename, **options):
44+
self.stdout.write("Importing from %s" % filename)
45+
46+
current_generation = Generation.objects.current()
47+
new_generation = Generation.objects.new()
48+
49+
file_type = options["file_type"].value.lower()
50+
generalized = options["generalized"]
51+
52+
if file_type == "lsoa": # England and Wales
53+
feat_name = 'LSOA11NM'
54+
feat_code = 'LSOA11CD'
55+
elif file_type == "msoa": # England and Wales
56+
feat_name = 'MSOA11NM'
57+
feat_code = 'MSOA11CD'
58+
elif file_type == "soa": # super output areas - NI
59+
feat_name = 'SOA_LABEL'
60+
feat_code = 'SOA_CODE'
61+
elif file_type == "dz": # datazone - scotland
62+
feat_name = 'Name'
63+
feat_code = 'DataZone'
64+
elif file_type == "iz": # intermediate zone - scotland
65+
feat_name = 'Name'
66+
feat_code = 'InterZone'
67+
else:
68+
raise Exception(
69+
"Need to specify a small area type (lsoa, dz, soa, lz, msoa)")
70+
71+
if file_type in ["lsoa", "dz", "soa"]:
72+
area_type = 'OLF'
73+
elif file_type in ["msoa", "iz"]:
74+
area_type = 'OMF'
75+
76+
if generalized:
77+
area_type = area_type[:2] + "G"
78+
79+
ds = DataSource(filename)
80+
layer = ds[0]
81+
for feat in layer:
82+
# retrieve name and code, and set country
83+
name = feat[feat_name].value
84+
code = feat[feat_code].value
85+
if code[:2] == "95":
86+
country = "N"
87+
else:
88+
country = code[0]
89+
90+
self.stdout.write(" looking at '%s' (%s)" % (name, code))
91+
92+
g = feat.geom.transform(settings.MAPIT_AREA_SRID, clone=True)
93+
94+
# skip if the SOA already exists in db (SOAs don't change)
95+
areas = Area.objects.filter(type__code=area_type, codes__code=code)
96+
if len(areas):
97+
m = areas[0]
98+
# check that we are not about to skip a generation
99+
if m.generation_high and current_generation and m.generation_high.id < current_generation.id:
100+
raise Exception("Area %s found, but not in current generation %s" % (m, current_generation))
101+
if m.generation_high != new_generation and options['commit']:
102+
m.generation_high = new_generation
103+
m.save()
104+
continue
105+
106+
print("Adding %s (%s) %s" % (name, code, feat.geom.geom_name))
107+
m = Area(
108+
name=name,
109+
type=Type.objects.get(code=area_type),
110+
country=Country.objects.get(code=country),
111+
generation_low=new_generation,
112+
generation_high=new_generation,
113+
)
114+
115+
poly = [g] if g is not None else []
116+
117+
if options['commit']:
118+
m.save()
119+
m.names.update_or_create(type=NameType.objects.get(
120+
code='S'), defaults={'name': name})
121+
m.codes.update_or_create(type=CodeType.objects.get(
122+
code='ons'), defaults={'code': code})
123+
save_polygons({m.id: (m, poly)})

0 commit comments

Comments
 (0)