Geographies

A geography (or place) is identified uniquely by a level and a code which, when combined, form its geoid. Each level describes a different way of breaking up a country and can be units such as country, province, municipality, state or county. The code is some ID that is unique for that level, either a number or a string.

Some example geoids are:

  • province-WC: the Western Cape province in South Africa
  • country-KE: Kenya
  • ward-19100057: ward 19100057 in Cape Town, South Africa
  • county-1: the Mombasa county in Kenya

Geographies are stored in the wazimap_geographies table using the Geography Django model.

class wazimap.models.Geography(id, geo_level, geo_code, name, long_name, year, square_kms, parent_level, parent_code)[source]

Adding Geographies

The geography database table looks something like the following. It’s generally easiest to import this data using PostgreSQL’s CSV import support.

geo_level geo_code name year parent_level parent_code
country KE Kenya 2009    
county 1 Mombasa 2009 country KE
county 2 Kwale 2009 country KE
county 3 Kilifi 2009 country KE

Level Hierarchy

The geography levels form a hierarchy with a single root geography (generally a country). The levels configuration option describes each level in the hierarchy.

Maps and boundary data

Wazimap needs to know boundary information for each geography so that it can draw shapes on maps and include the boundaries in download formats such as KML and GeoJSON.

The easiest way to provide this information is as a GeoJSON FeatureCollection. You can either have one big file, or one file for each geo level.

  1. Create a .geojson file with single FeatureCollection object. Each Feature in the collection must be a geography in Wazimap. It must have the following attributes:

    • name: the name of the place (same as the geography name)
    • level: the geography level of the place, same as the geo_level in the database
    • code: the code for the geography, same as the geo_code in the database
    • geoid: the unique id for this geography, which must be the level-code.
  2. Store this file in your Django app’s static folder, such as wazimap_ke/static/geo/.

  3. Set the geometry_data configuration option in your settings.py to indicate where each level’s geojson file is stored, relative to you static folder. For example:

    geometry_data = {
      'country': 'geo/country.geojson',
      'province': 'geo/province.geojson',
    }
    
  4. GeoJSON files can be quite big for geographies that share lots of boundaries. If you want an improvement in speed and size, also convert each file to a TopoJSON file using the topojson NPM tool. Then place these files alongside your geojson files and change your geometry_data settings to point to the .topojson files:

    geometry_data = {
      'country': 'geo/country.topojson',
      'province': 'geo/province.topojson',
    }
    

    Note

    It’s important to have both the TopoJSON and GeoJSON formats. Wazimap will look for the GeoJSON format when loading the boundary information for use on the server, such as for geolocation. This is necessary because Python doesn’t have a good TopoJSON library.

Geo Data API

Wazimap makes geography data available through the wazimap.geo.geo_data object, which is detailed below.

The class used for this object can be configured using the geodata setting. This allows you to change this behaviour if you need to.

class wazimap.geo.GeoData[source]

General Wazimap geography helper object.

This object helps Wazimap load geographies, navigate geo level hierarchies, find locations, etc. It’s a good place to override this functionality if you want to use a different geometry setup.

To override behaviour, implement your own GeoData object (probably inheriting from this one), then set the WAZIMAP[‘geodata’] to the dotted path of your new class in your settings.py. Wazimap will then load that class and make it available as wazimap.geo.geo_data.

get_geography(geo_code, geo_level)[source]

Get a geography object for this geography, or raise LocationNotFound if it doesn’t exist.

get_geometry(geo_level, geo_code)[source]

Get the geometry description for a geography. This is a dict with two keys, ‘properties’ which is a dict of properties, and ‘shape’ which is a shapely shape (may be None).

get_locations(search_term, levels=None, year=None)[source]

Try to find locations based on a search term, possibly limited to +levels+.

Returns an ordered list of geo models.

get_locations_from_coords(longitude, latitude, levels=None)[source]

Returns a list of geographies containing this point.

get_summary_geo_info(geo_code=None, geo_level=None)[source]

Get a list of (level, code) tuples of geographies that this geography should be compared against.

This is the intersection of +comparative_levels+ and the ancestors of the geography.

root_geography()[source]

First geography with no parents.

setup_geometry()[source]

Load boundaries from geojson shape files.

setup_levels()[source]

Setup the summary level hierarchy from the WAZIMAP[‘levels’] and WAZIMAP[‘comparative_levels’] settings.