Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

experiment importing statcan data #63

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/cmd/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
yargs.positional('source', {
type: 'string',
describe: 'name of data source',
choices: ['whosonfirst', 'osmium', 'zcta'],
choices: ['whosonfirst', 'osmium', 'zcta', 'statcan'],
demand: 'source is required'
})

Expand Down
8 changes: 8 additions & 0 deletions import/source/statcan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const file = require('../../import/file')

module.exports = {
ingress: file,
record_separator: /\r?\n/,
format: 'json',
mapper: require('./statcan/map/place')
}
1 change: 1 addition & 0 deletions import/source/statcan/download.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://www12.statcan.gc.ca/census-recensement/2011/geo/bound-limit/bound-limit-eng.cfm
17 changes: 17 additions & 0 deletions import/source/statcan/map/geometries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const _ = require('lodash')
const format = require('../../../format')
const Geometry = require('../../../../model/Geometry')

function mapper (place, doc) {
const geometry = _.get(doc, 'geometry')
const isPolygon = _.get(geometry, 'type', '').trim().toUpperCase().endsWith('POLYGON')

if (geometry) {
place.addGeometry(new Geometry(
format.from('geometry', 'geojson', geometry),
isPolygon ? 'boundary' : 'centroid'
))
}
}

module.exports = mapper
112 changes: 112 additions & 0 deletions import/source/statcan/map/geometries.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
const Place = require('../../../../model/Place')
const Geometry = require('../../../../model/Geometry')
const map = require('./geometries')

module.exports.tests = {}

module.exports.tests.mapper = (test) => {
test('mapper: geometry empty', (t) => {
let p = new Place()
map(p, {})

t.equals(p.geometry.length, 0)
t.end()
})
test('mapper: maps polygon', (t) => {
let p = new Place()
map(p, {
geometry: {
'type': 'Polygon',
'coordinates': [
[
[
39.0234375,
48.922499263758255
],
[
47.8125,
39.639537564366684
],
[
61.17187499999999,
49.83798245308484
],
[
39.0234375,
48.922499263758255
]
]
]
}
})
t.equals(p.geometry.length, 1)
t.true(p.geometry[0] instanceof Geometry)
t.equal(p.geometry[0].geometry.constructor.name.toUpperCase(), 'POLYGON')
t.equal(p.geometry[0].role, 'boundary')
t.end()
})
test('mapper: maps point', (t) => {
let p = new Place()
map(p, {
geometry: {
'type': 'Point',
'coordinates': [
59.0625,
47.989921667414194
]
}
})
t.equals(p.geometry.length, 1)
t.true(p.geometry[0] instanceof Geometry)
t.equal(p.geometry[0].geometry.constructor.name.toUpperCase(), 'POINT')
t.equal(p.geometry[0].role, 'centroid')
t.end()
})
test('mapper: internal point', (t) => {
let p = new Place()
map(p, {
geometry: {
'type': 'Polygon',
'coordinates': [
[
[
39.0234375,
48.922499263758255
],
[
47.8125,
39.639537564366684
],
[
61.17187499999999,
49.83798245308484
],
[
39.0234375,
48.922499263758255
]
]
]
},
properties: {
'INTPTLON10': 1.1,
'INTPTLAT10': 2.2
}
})
t.equals(p.geometry.length, 2)
t.true(p.geometry[1] instanceof Geometry)
t.equal(p.geometry[1].geometry.constructor.name.toUpperCase(), 'POINT')
t.equal(p.geometry[1].role, 'centroid')
t.end()
})
}

module.exports.all = (tape) => {
function test (name, testFunction) {
return tape(`geometries: ${name}`, testFunction)
}

for (var testCase in module.exports.tests) {
module.exports.tests[testCase](test)
}
}
9 changes: 9 additions & 0 deletions import/source/statcan/map/names.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const _ = require('lodash')
const Name = require('../../../../model/Name')

function mapper (place, properties) {
// generic name properties
place.addName(new Name('eng', 'default', false, _.get(properties, 'CDNAME', '').trim()))
}

module.exports = mapper
35 changes: 35 additions & 0 deletions import/source/statcan/map/names.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const Place = require('../../../../model/Place')
const map = require('./names')

module.exports.tests = {}

module.exports.tests.mapper = (test) => {
test('mapper: properties empty', (t) => {
let p = new Place()
map(p, {})

t.equals(p.name.length, 0)
t.end()
})
test('mapper: name', (t) => {
let p = new Place()
map(p, { 'ZCTA5CE10': ' example1 ' })

t.equals(p.name.length, 1)
t.equals(p.name[0].lang, 'und')
t.equals(p.name[0].tag, 'default')
t.equals(p.name[0].abbr, false)
t.equals(p.name[0].name, 'example1')
t.end()
})
}

module.exports.all = (tape) => {
function test (name, testFunction) {
return tape(`names: ${name}`, testFunction)
}

for (var testCase in module.exports.tests) {
module.exports.tests[testCase](test)
}
}
42 changes: 42 additions & 0 deletions import/source/statcan/map/place.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const _ = require('lodash')
const Identity = require('../../../../model/Identity')
const Ontology = require('../../../../model/Ontology')
const Place = require('../../../../model/Place')

const map = {
properties: require('./properties'),
names: require('./names'),
geometries: require('./geometries')
}

// {
// "CSDUID": "5933045",
// "CSDNAME": "Sun Peaks Mountain",
// "CSDTYPE": "VL",
// "PRUID": "59",
// "PRNAME": "British Columbia / Colombie-Britannique",
// "CDUID": "5933",
// "CDNAME": "Thompson-Nicola",
// "CDTYPE": "RD"
// }

function mapper (doc) {
// get document properties
const properties = _.get(doc, 'properties')
if (!_.isPlainObject(properties)) { return null }

// instantiate a new place
const place = new Place(
new Identity('statcan', _.get(properties, 'CDUID', '').trim()),
new Ontology('admin', _.get(properties, 'CDTYPE', '').trim())
)

// run mappers
map.properties(place, properties)
map.names(place, properties)
map.geometries(place, doc)

return place
}

module.exports = mapper
48 changes: 48 additions & 0 deletions import/source/statcan/map/place.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const Place = require('../../../../model/Place')
const map = require('./place')

module.exports.tests = {}

module.exports.tests.mapper = (test) => {
test('mapper: properties empty', (t) => {
let place = map({})
t.equal(place, null)
t.end()
})
test('mapper: maps identity & ontology', (t) => {
let place = map({
properties: {
'ZCTA5CE10': '90210'
}
})
t.true(place instanceof Place)
t.equal(place.identity.source, 'uscensus')
t.equal(place.identity.id, 'zcta:90210')
t.equal(place.ontology.class, 'admin')
t.equal(place.ontology.type, 'postalcode')
t.end()
})
test('mapper: maps geometry', (t) => {
let place = map({
properties: {
'ZCTA5CE10': '90210'
},
geometry: require('../../../../test/fixture/geojson.triangle')
})
t.true(place instanceof Place)
t.equal(place.geometry.length, 1)
t.equal(place.geometry[0].geometry.constructor.name.toUpperCase(), 'POLYGON')
t.equal(place.geometry[0].role, 'boundary')
t.end()
})
}

module.exports.all = (tape) => {
function test (name, testFunction) {
return tape(`place: ${name}`, testFunction)
}

for (var testCase in module.exports.tests) {
module.exports.tests[testCase](test)
}
}
9 changes: 9 additions & 0 deletions import/source/statcan/map/properties.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const Property = require('../../../../model/Property')

function mapper (place, properties) {
for (let key in properties) {
place.addProperty(new Property(`statcan:${key}`, properties[key]))
}
}

module.exports = mapper
40 changes: 40 additions & 0 deletions import/source/statcan/map/properties.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const Place = require('../../../../model/Place')
const map = require('./properties')

module.exports.tests = {}

module.exports.tests.mapper = (test) => {
test('mapper: properties empty', (t) => {
let p = new Place()
map(p, {})

t.equals(p.property.length, 0)
t.end()
})
test('mapper: uscensus-specific properties', (t) => {
let p = new Place()
map(p, {
'CLASSFP10': 'B5',
'MTFCC10': 'G6350',
'INTPTLON10': 1.1,
'INTPTLAT10': 2.2
})

t.equals(p.property.length, 2)
t.equals(p.property[0].key, 'uscensus:CLASSFP10', 'CLASSFP10')
t.equals(p.property[0].value, 'B5', 'CLASSFP10')
t.equals(p.property[1].key, 'uscensus:MTFCC10', 'MTFCC10')
t.equals(p.property[1].value, 'G6350', 'MTFCC10')
t.end()
})
}

module.exports.all = (tape) => {
function test (name, testFunction) {
return tape(`properties: ${name}`, testFunction)
}

for (var testCase in module.exports.tests) {
module.exports.tests[testCase](test)
}
}