Animating geodemographic data with D3

What’s here

  • Some thoughts on the cost of establishing provincial bodies to design, deliver, and monitor public services whose geographic boundaries are misaligned with the national census
  • An extensive collection of geodemographic files
  • Some cool (at least I think so!) data visualizations involving sliders and animation

An aside

Since last time, I have been familiarizing myself with some of the more technical details of the Canadian government’s census and the administrative bodies that the Ontario government has established to plan, deliver, and monitor health and human services. In many instances, the geographic boundaries of these administrative bodies are difficult – if not impossible – to align with Canada’s census divisions, census subdivisions, dissemination areas, dissemination blocks, and other geographic units. This misalignment seriously challenges the use of expensive census data to address the social determinants of health and well-being in our public services. 1 The cost of this misalignment needs to figure more prominently and explicitly in any future decisions to establish new or modify existing administrative bodies. In this regard, the decision of the Ministry of Children and Youth to align the geographic boundaries of its five Integrated Service Regions (ISRs) and its thirty-three children and youth mental health Service Areas (CYMHSAs) with Ontario’s census divisions is commendable.

New geodemographic datasets

I have to admit that earlier posts have run the risk of presenting a somewhat disjointed view of the population projections and the geographic boundaries of administrative bodies that the Ontario government has established to plan, deliver, and monitor health and human services. So I want to consolidate some of my thinking and share a number of geodemographic datasets that will form the basis of future data analyses and visualizations. I have structured these datasets using three main categories – geographic unit, classification of age, and demographic variable – each with a number of sub-types:

  • Geographic Unit (4)
    • Statistics Canada
      • Census Division (CD)
    • Ontario Ministry of Children and Youth Services
      • Child and Youth Mental Health Service Area (CYMHSA)
      • Integrated Service Region (ISR)
    • Ontario Ministry of Health and Long Term Care
      • Local Health Integration Network (LHIN)
  • Classification of Age (5)
    • Life Cycle Grouping (LCG)
      • Child (0 – 14)
      • Youth (15 – 24)
    • Young Person
      • LCG-Child and LCG-combined (0 – 24)
      • CFSA-Child (0 – 17)
    • Transitional-Age Person
      • Emerging Adult (16 – 20)
  • Demographic Variable (7)
    • Population
    • Population Density
    • Population Share
    • Population Growth
      • Annual Growth
        • Change in number of persons
        • Rate of growth (%)
      • 5 Year Growth
        • Change in number of persons
        • Rate of growth (%)

We have met with most of these categories and sub-types before, or they carry their usual meanings here. One exception is the CFSA-Child (0 – 17) classification of age, which refers to the definition of “child” under the Child and Family Services Act in Ontario. CFSA-Child is central to any data analyses and visualizations relating to the CYMHSAs and ISRs defined by the province’s Ministry of Children and Youth.

We have compiled twenty-eight datasets in *.csv format that profile the different classifications of age for the years 2016 to 2041:2

Table 1. Datafiles for five classifications of age (above), 2016 to 2041 within a Geographic Unit x Demographic Variable tuple.
Geographic Unit
Demographic Variable CD CYMHSA ISR LHIN
Population data data data data
Population density data data data data
Population share data data data data
Growth
   Annual growth
       Change in number of persons data data data data
       Rate of growth (%) data data data data
   5-year growth
       Change in number of persons data data data data
       Rate of growth (%) data data data data

Sliders and animations

Of course, compiling all of these geodemographic datasets is only worthwhile if we can use them to make better decisions. In earlier posts, we have illustrated how to generate static maps of the geographic boundaries of administrative bodies like the MCYS’s CYMHSAs and ISRs, the MOHLTC’s LHINs, and we have introduced some limited capabilities for the user to interact (zoom, pan) with more dynamic maps.

Before leaving off here, I wanted to illustrate the use of sliders and animation to enhance the user’s abilities – not only to interact with maps – but to discern spatial-temporal patterns in the demographic data.

First, let’s introduce a slider that allows the user to move forward and backwards in time as we use a choropleth map to illustrate the rate of growth in the Child (0 – 14) population in Ontario’s fourty-nine Census Divisions, 2016 to 2041 [interactive version]:

Screen CDS GrowthPC Child slider
Figure 1. Choropleth with slider, illustrating annual rate of growth in Child (0 – 14) population by Census Division in Ontario, 2016 to 2041.

Second, let’s use animation to display the same data [interactive version]:

Screen CDS GrowthPC Child animation
Figure 2. Choropleth with animation, illustrating annual rate of growth in Child (0 – 14) population by Census Division in Ontario, 2016 to 2041.

Next time: I will provide a (fairly) friendly interface that will allow users to select among the 140 possible combinations of Classification of Age x Demographic Variable x Geographic Unit.

 

  1. For example, consider the challenge that Ontario’s Ministry of Finance confronts when it provides population projections for Ontario’s Local Health Integration Networks (LHINs). Except for a few cases, the boundaries of the LHINs do not conform to those of Census Divisions (CDs) or Census Subdivisions (CSDs). Thus, to take advantage of Statistics Canada’s annual updates of population projections to revise the basic demographic profiles of the LHINs, the Ministry of Finance must resort to a number of fiddles, depending on how a particular LHIN splits one or more CDs and/or CSDs. Case 1: If the LHIN consists of intact CDs (the Erie St. Clair LHIN), the Ministry of Finance’s CD-level projections for each CD are aggregated. Case 2: If the LHIN does not include any part of Toronto, York, and Peel AND its boundary splits CDs but not CSDs (the Champlain, South East, North-East, and North-West LHINs), the share-of-growth method is used. Case 3:  If the LHIN boundary splits CSDs (as well as CDs) in Toronto, York, and Peel (the Central West, Mississauga Halton, Toronto Central, and Central East LHINs), the share-of-growth method is used based on the growth of Dissemination Areas. Case 4: If the LHIN boundary splits CSDs (as well as CDs) in CDs other than Toronto, York, and Peel (the South West, Waterloo-Wellington, Hamiltion Niagara Haldimand Brant, Central, and North Simcoe Muskoka LHINs), the constant-share method is used. Additional iterative prorating procedure is required to deal with the age-sex structure of CSDs and split CSDs. All of this merely to update basic population projections! Imagine the impracticality, if not impossibility, of taking advantage of Statistics Canada’s periodic updates of subtler, and potentially more valuable, census-based socioeconomic data.
  2. For a given year within these twenty-eight datasets, the data corresponding to the Child, Youth, LCG-Combined, CFSA-Child, and Emerging Adult classifications of age are identified with the prefix Child_, Youth_, Young_, CFSAC_, and Mixed_, respectively, plus a suffix for the year. For data relating to annual growth of population, the suffix refers to the later year in the comparison.

Population Projections across CYMH Service Areas, 2016-2041

Population Projections

Recently the Ministry of Finance updated its population projections for Ontario, 2016 – 2041. These population projections are organized into 4 different datasets:

  • projections for the whole province
  • projections for each census division
  • projections for each Local Health Integration Network (LHIN)
  • projections for each Ministry of Children and Youth Services’ Service Delivery Division (SDD) region

Each dataset includes population projections by age and gender.

From the population projections for each census division (CD), we have derived the population projections (summing projections for Males and Females) for each of the CYMH Service Areas, 2016 – 2041.

The result of our work is presented in one spreadsheet, that includes six worksheets:

  • Ages x Year (Base): Population projections for each Age between 0 – 24 years by Year
  • 0-18 x Year: Population projections for the total number of 0 – 18 year old children and youth by Year
  • 0-24 x Year: Population projections for the total number of 0 – 24 year old children and youth by Year
  • 0-18 x Age Group x Year: Population projections for children and youth grouped into 5 year spans (0-4, 5-9, 10-14, and 15-18 years old)
  • 0-24 x Age Group x Year: Population projections for children and youth grouped into 5 year spans (0-4, 5-9, 10-14, 15-19, and 20-24 years old)
  • 0-24 x Life Cycle x Year: Population projections for children and youth grouped into two Life Cycle spans (Child, 0 – 14 years old and Youth, 15 – 24 years old)

Population Density

We have also calculated the land area of the individual CYMH Service Areas in order to derive their respective projected population densities. We will soon provide a speadsheet with these projections as well.

For now, let’s use the worksheet containing the projections of population and population densities for 0 – 18 year olds to add some (non-geospatial) data finally to our visualization of the CYMH Service Areas. Our illustration of two mapping techniques – proportional symbol representation (for the population projections) and choropleth (for the projected population densities) – will be illustrative only.

Proportional Symbol Representation of Population Projections

We may represent the projected number of 0 – 18 year olds across all CYMH Service Areas in a given year by combining geospatial data (in the familiar TopoJSON file format) with demographic data (in .csv format):

Proportional Symbol representation of projected population of 0-18 year olds screenshot
Figure 1. Proportional symbol representation of projected population of 0 – 18 year olds across the CYMH Service Areas in 2020.

[Interactive page – try hovering the mouse over a bubble]

Choropleth Representation of Projected Population Densities

We may also represent the projected density of 0 – 18 year olds across all CYMH Service Areas in a given year by combining geospatial data (in the familiar TopoJSON file format) with demographic data (in .csv format):

Choropleth Population Density 0-18 year olds screenshot
Figure 2. Choropleth representation of projected population density of 0 – 18 year olds across the CYMH Service Areas in 2020.

[Interactive page – try hovering the mouse over a CYMH Service Area]

Next time: We’ll look at increasing user interaction with choropleths and proportional symbol representations – including animation!

Overlaying the boundaries of the Local Health Integration Networks and Children and Youth Mental Health Service Areas in Ontario

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

In a series of previous posts, we have visualized the boundaries of the MCYS Integrated Service Regions (ISRs) and the MCYS Children and Youth Mental Health (CYMH) Service Areas.

Now we want to merge the digital boundaries of the CYMH Service Areas with the MOHLTC’s Local Health Integration Networks (LHINs) in Ontario.

The boundaries of the LHINs in 2015 are provided in the ESRI ® shapefile format (HRL035b11a_e.zip) by Statistics Canada. The .zip file contains four familiar files:

  • HRL03b11a_e.dbf
  • HRL03b11a_e.prj
  • HRL03b11a_e.shp
  • HRL03b11a_e.shx

The projection information in the HRL03b11a_e.prj file indicates that the geospatial data for the LHINs uses the EPSG 3347 PCS Lambert Conformal Conic projection. 1 So we convert the original shapefile for the LHINs to the same projection (EPSG 4269) used for the CYMH Service Areas:

ogr2ogr -f 'ESRI Shapefile' -t_srs EPSG:4269 lhins.shp HRL035a11a_e_Sept2015.shp

Next we convert the new shapefile lhins.shp to a GeoJSON file and then to a TopoJSON file (see Visualizing the MCYS Integrated Service Regions Using d3.geo for the details of this process):

ogr2ogr -t_srs EPSG:4269 -f GeoJSON lhins_geo.json lhins.shp
topojson -o lhins_topo.json --properties -- lhins_geo.json

Finally, to merge the TopoJSON file for the CYMH Service Areas and the TopoJSON file for the LHINs into a single TopoJSON file, we need to install the utility geojson-merge:

npm install -g geojson-merge

and then run:

geojson-merge cymhsas_geo.json lhins_geo.json > cymhsas_lhins_geo.json

The properties of cymhsas_lhins_topo.json include:

HR_UID -> idHealth Region ID

Property Value
area_index Identifier of CYMH Service Area
area_name Name of CYMH Service Area
ENG_LABEL -> lhin_name Name of LHIN (English)
FRE_LABEL Name of LHIN (French)

We use Notepad++ to rename ENG_LABEL to lhin_name. We then promote HR_UID to the id property of the TopoJSON file.

topojson -o cymhsas_lhins_topo.json --id-property HR_UID --properties -- cymhsas_lhins_geo.json

And finally, we use Notepad++ to add the isr and color properties to the CYMH Service Areas.

Notes:

Our visualization of the MCYS and MOHLTC geospatial data includes the following features:

  • the five Integrated Service Regions and their respective CYMH Service Areas are distinguished with different hues
  • the boundary and name of a Local Health Integrated Network are displayed when the user hovers the mouse over one of the thirteen LHINs
  • the user may pan and zoom in on the visualization

Our visualization requires only these few modifications of the Javascript we developed to display the names of the CYMH Service Areas:

/* CSS */
...
.lhin_area:hover{
  stroke: #000;
  stroke-width: 1.5 px;
}

/* Javascript */
...

function draw(topo) {

var service_area = g.selectAll(".area_name").data(topo);

/* Visualize the CYMH Service Areas in colour, use id index to assign transparent colour to LHINs */
service_area.enter().insert("path")
.attr("class", "lhin_area")
.attr("d", path)
.attr("id", function(d,i) { return d.id; })
.style("fill", function(d,i) { return i <= 32 ? d.properties.color : 'transparent' });

/* define offsets for displaying the tooltips */
var offsetL = document.getElementById('map').offsetLeft+20;
var offsetT = document.getElementById('map').offsetTop+10;

/* toggle display of tooltips in response to user mouse behaviours*/
service_area

.on("mousemove", function(d,i) {
var mouse = d3.mouse(svg.node()).map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(d.properties.lhin_name);
})

.on("mouseout", function(d,i) {
tooltip.classed("hidden", true);
});

}

… yielding the following visualization (interactive version):

Overlay LHINs on CYMH Service Areas
Figure 1. Screenshot of LHIN superimposed on CYMH Service Areas.

Next time: We’ll begin to merge the geospatial data in our TopoJSON files with demographic data in the public domain.

 

  1. Using Prj2EPSG.

Adding pan and zoom to a visualization of the CYMH Service Areas in Ontario

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

In previous posts, we have described:

  1. method for partitioning the Ontario government’s Shapefile archive of the thirty-four thirty-three MCYS Children and Youth Mental Health (CYMH) Service Areas into five groupings, corresponding to the MCYS Integrated Service Regions (ISRs)
  2. a method for using the TopoJSON files to visualize the CYMH Service Areas within the separate ISRs
  3. the addition of tooltips to display the names of the CYMH Service Areas across Ontario
  4. the addition of a responsive framework to ensure that our visualizations accommodate to the display capabilities of various PCs, laptops, tablets, and smart phones

Here we highlight the additional code that’s required to allow the user to pan and zoom the visualization of the CYMH Service Areas with tooltips (#3  above):

<!DOCTYPE html>
<meta charset="utf-8">
<style>

/* CSS goes here */

/* define the container element for our map */
#map {
 margin:5% 5%;
 border:2px solid #000;
 border-radius: 5px;
 height:100%;
 overflow:hidden;
 background: #FFF;
}

/* style of the text box containing the tooltip */

div.tooltip {
 color: #222; 
 background: #fff; 
 padding: .5em; 
 text-shadow: #f5f5f5 0 1px 0;
 border-radius: 2px; 
 box-shadow: 0px 0px 2px 0px #a6a6a6; 
 opacity: 0.9; 
 position: absolute;
}

/* style of the text displayed in text box of the tooltip when mouse is hovering over a CYMH Service Area */

.service_area:hover{ stroke: #fff; stroke-width: 1.5px; }

.text{ font-size:10px; }

/* otherwise, the text box of the tooltip is hidden */
.hidden { 
 display: none; 
}

</style>
<body>

/* create the container element #map */
<div id="map"></div>

/* load Javascript libraries for D3 and TopoJSON */
<script src="//d3js.org/d3.v3.min.js"></script>
<script src= "//d3js.org/topojson.v1.min.js"></script>

<script> // begin Javascript for visualizing the geo data

/* define some global variables */

var topo, projection, path, svg, g;

/* 1. Set the width and height (in pixels) based on the offsetWidth property of the container element #map */

var width = document.getElementById('map').offsetWidth;
var height = width / 2;

/* Call function setup() to create empty root SVG element with width, height of #map */

setup(width,height);

function setup(width,height){

/* 2. Create an empty root SVG element */
d3.behavior.zoom(), constructs a zoom behavior that creates an even listener to handle zoom gestures (mouse and touch) on the SVG elements you apply the zoom behavior onto

svg = d3.select('#map').append('svg')
 .style('height', height + 'px')
 .style('width', width + 'px')
.append('g') 
.call(zoom);

g = svg.append('g')
    .on("click", click);

} // end setup()

/* 3. Define Unit Projection using Albers equal-area conic projection */

var projection = d3.geo.albers()
 .scale(1)
 .translate([0,0]);

/* 4. Define the path generator - to format the projected 2D geometry for SVG */

var path = d3.geo.path()
 .projection(projection);

/* 5.0 Start function d3.json() */
/* 5.1 Load the TopoJSON data file */

d3.json("http://cartoserve.com/maps/ontario/cymhsas33_data/cymhsas_topo.json", function(error, cymhsas_topo) {
if (error) return console.error(error);

/* 5.2 Convert the TopoJSON data back to GeoJSON format */
/* and render the map using Unit Projection */

var areas_var = topojson.feature(cymhsas_topo, cymhsas_topo.objects.cymhsas_geo);

/* 5.2.1 Calculate new values for scale and translate using bounding box of the service areas */
 
var b = path.bounds(areas_var);
var s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

/* 5.2.2 New projection, using new values for scale and translate */
projection
 .scale(s)
 .translate(t);

/* redefine areas_var in terms of the .features array, assign array to topo */
var areas_var = topojson.feature(cymhsas_topo, cymhsas_topo.objects.cymhsas_geo).features;

topo = areas_var;

/* make the map by calling our draw() function initially within the d3.json callback function */
 
draw(topo);

}); // end function d3.json

function draw(topo) {

var service_area = g.selectAll(".area_name").data(topo);

service_area.enter().insert("path")
.attr("class", "service_area")
.attr("d", path)
.attr("id", function(d,i) { return d.id; })
.style("fill", function(d, i) { return d.properties.color; })
.attr("title", function(d,i) { return d.properties.area_name; });

/* define offsets for displaying the tooltips */
var offsetL = document.getElementById('map').offsetLeft+20;
var offsetT = document.getElementById('map').offsetTop+10;

/* toggle display of tooltips in response to user mouse behaviours*/
service_area
// begin mousemove
.on("mousemove", function(d,i) {
var mouse = d3.mouse(svg.node()).map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(d.properties.area_name);
}) // end mousemove
// begin mouseout
.on("mouseout", function(d,i) {
tooltip.classed("hidden", true);
}); // end mouseout

} // end draw()

function move() {

 var t = d3.event.translate;
 var s = d3.event.scale; 
 zscale = s;
 var h = height/4;

 t[0] = Math.min(
 (width/height) * (s - 1), 
 Math.max( width * (1 - s), t[0] )
 );

 t[1] = Math.min(
 h * (s - 1) + h * s, 
 Math.max(height * (1 - s) - h * s, t[1])
 );

 zoom.translate(t);
 g.attr("transform", "translate(" + t + ")scale(" + s + ")");

 //adjust the Service Area hover stroke width based on zoom level
 d3.selectAll(".service_area").style("stroke-width", 1.5 / s);

}

/* our function click() uses the .invert() configuration method */
/* to project backward from Cartesian coordinates (in pixels) to spherical coordinates (in degrees) */

function click() {
 var latlon = projection.invert(d3.mouse(this));
 console.log(latlon);
}

</script> // end Javascript for visualizing the geo data

Giving us the following interactive visualization of the CYMH Service Areas in Ontario.

Next time: We will show how to merge our visualization of the geography of the CYMH Service Areas with other data about the populations and service providers within these Service Areas.

A responsive framework for visualizing CYMH Service Areas in Ontario

In previous posts (1, 2, 3) we described a method for visualizing geographic representations of Integrated Service Regions (ISRs) and Children and Youth Mental Health Service Areas (CYMHSAs) in Ontario using free and open source software.

This brief note is to advise we are now running D3 in tandem with Bootstrap – a responsive framework that ensures that our visualizations accommodate to the display capabilities of a wide range of digital devices, including PCs, laptops, tablets, and smartphones. 1

 

  1. See our guidelines for installing Bootstrap on a Linux server.

Consolidating and enhancing the visualization of CYMH Service Areas in Ontario

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

In previous posts, we provided the following:

  • method for partitioning the Ontario government’s Shapefile archive of the thirty-four MCYS Children and Youth Mental Health (CYMH) Service Areas into five groupings, corresponding to the MCYS Integrated Service Regions (ISRs)
  • a method for using the TopoJSON files to visualize the CYMH Service Areas within the separate ISRs
  • the addition of a responsive framework to ensure that our visualizations accommodate to the display capabilities of various PCs, laptops, tablets, and smart phones

In this post, we describe how to enhance the functionality of our visualization of the Integrated Service Regions and CYMH Service Areas and Integrated across the entire province of Ontario.

Consolidated Geodata Files for CYMH Service Areas in Ontario

In a previous post, we provided a set of GeoJSON and TopoJSON files for the individual CYMH Service Areas and their groupings into the five distinct ISRs.

For present purposes, we have created two geodata files – in GeoJSON and TopoJSON formats – for the entire set of CYMH Service Areas in Ontario.

Field Property of the CYMH Service Area
area_name Name
id ID
isr Integrated Service Region
color Color

Simple Maps of the CYMH Service Areas

By way of a quick review, let’s start with a simple map outlining the CYMH Service Areas in Ontario:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

/* CSS goes here */

/* define the container element for our map */
#map {
 margin:5% 5%;
 border:2px solid #000;
 border-radius: 5px;
 height:100%;
 overflow:hidden;
 background: #FFF;
}

</style>
<body>

/* create the container element #map */
<div id="map"></div>

/* load Javascript libraries for D3 and TopoJSON */
<script src="//d3js.org/d3.v3.min.js"></script>
<script src= "//d3js.org/topojson.v1.min.js"></script>

<script> // begin Javascript for visualizing the geo data

/* define some global variables */

var topo, projection, path, svg, g;

/* 1. Set the width and height (in pixels) based on the offsetWidth property of the container element #map */

var width = document.getElementById('map').offsetWidth;
var height = width / 2;

/* Call function setup() to create empty root SVG element with width, height of #map */

setup(width,height);

function setup(width,height){

/* 2. Create an empty root SVG element */

svg = d3.select('#map').append('svg')
 .style('height', height + 'px')
 .style('width', width + 'px')
 .append('g');

g = svg.append('g');

} // end setup()

/* 3. Define Unit Projection using Albers equal-area conic projection */

var projection = d3.geo.albers()
 .scale(1)
 .translate([0,0]);

/* 4. Define the path generator - to format the projected 2D geometry for SVG */

var path = d3.geo.path()
 .projection(projection);

/* 5.0 Start function d3.json() */
/* 5.1 Load the TopoJSON data file */

d3.json("http://cartoserve.com/maps/ontario/cymhsas33_data/cymhsas_topo.json", function(error, cymhsas_topo) {
if (error) return console.error(error);

/* 5.2 Convert the TopoJSON data back to GeoJSON format */
/* and render the map using Unit Projection */

var areas_var = topojson.feature(cymhsas_topo, cymhsas_topo.objects.cymhsas_geo);

/* 5.2.1 Calculate new values for scale and translate using bounding box of the service areas */
 
var b = path.bounds(areas_var);
var s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

/* 5.2.2 New projection, using new values for scale and translate */
projection
 .scale(s)
 .translate(t);

/* redefine areas_var in terms of the .features array, assign array to topo */
var areas_var = topojson.feature(cymhsas_topo, cymhsas_topo.objects.cymhsas_geo).features;

topo = areas_var;

/* make the map by calling our draw() function initially within the d3.json callback function */
 
draw(topo);

}); // end function d3.json


function draw(topo) {

 var service_area = g.selectAll(".area_name").data(topo);

 service_area.enter().insert("path") 
 .attr("class", "service_area")
 .attr("d", path);

} // end function draw()

</script> // end Javascript for visualizing the geo data

Giving us the following visualization of 33 Service Areas [actual web page]:

CYMH Service Areas 33
Figure 1. Basic outline of 33 CYMH Service Areas in Ontario.

Note that the Javascript for creating our map includes three functions:

  • d3.json() – a built-in function to load geo data from a TopoJSON file
  • setup() – our function to create an empty root SVG element
  • draw() – our function to render the geo data

By adding just two lines of code to our draw() function, we can colour the CYMH Service Areas:


...
function draw(topo) {
 var service_area = g.selectAll(".area_name").data(topo);
 service_area.enter().insert("path") 
 .attr("class", "service_area")
 .attr("d", path)
 .attr("id", function(d,i) { return d.id; })
 .style("fill", function(d, i) { return d.properties.color; });

...

Giving us this figure [actual web page]:

CYMH Service Areas 33 colour
Figure 2. Thirty-three CYMH Service Areas in Ontario.

Adding Tooltips

Figures 1 and 2 suffer from one obvious shortcoming: none of the CYMH Service Areas is labelled. Unfortunately, our approach to labeling the CYMH Service Areas within a single Integrated Service Region breaks down when we have to contend with the scale of Ontario taken as a whole:

cymhsas02.html w labels screenshot
Figure 3. CYMH Service Areas cluttered with fixed labels.

Our best alternative is to use a tooltips to display the name of a CYMH Service Area when the user’s mouse hovers over the corresponding area of the visualization. Adding this functionality requires two sorts of modification of our Javascript.

First, we must style the Tooltips, including:

  • styling the <div> container element corresponding to the text box within which the name of the CYMH Service Area will be displayed
  • styling the text that is displayed when the user’s mouse is hovering over a service area
  • styling the tooltip so that it is hidden when the user’s mouse is not hovering over any service area

… like so:

<style>

...

/* style of the text box containing the tooltip */

div.tooltip {
 color: #222; 
 background: #fff; 
 padding: .5em; 
 text-shadow: #f5f5f5 0 1px 0;
 border-radius: 2px; 
 box-shadow: 0px 0px 2px 0px #a6a6a6; 
 opacity: 0.9; 
 position: absolute;
}

/* style of the text displayed in text box of the tooltip when mouse is hovering over a CYMH Service Area */

.service_area:hover{ stroke: #fff; stroke-width: 1.5px; }

.text{ font-size:10px; }

/* otherwise, the text box of the tooltip is hidden */
.hidden { 
 display: none; 
}

</style>

Second, we must modify our draw() function to display/hide tooltips in response to the user’s mousemove and mouseout behaviours:


<script>

var tooltip = d3.select("#map").append("div").attr("class", "tooltip hidden");

...

function draw(topo) {

var service_area = g.selectAll(".area_name").data(topo);

service_area.enter().insert("path")
.attr("class", "service_area")
.attr("d", path)
.attr("id", function(d,i) { return d.id; })
.style("fill", function(d, i) { return d.properties.color; })
.attr("title", function(d,i) { return d.properties.area_name; });

/* define offsets for displaying the tooltips */
var offsetL = document.getElementById('map').offsetLeft+20;
var offsetT = document.getElementById('map').offsetTop+10;

/* toggle display of tooltips in response to user mouse behaviours*/
service_area
//mousemove behaviour
.on("mousemove", function(d,i) {
var mouse = d3.mouse(svg.node()).map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(d.properties.area_name);
}) // end mousemove
// mouseout behaviour
.on("mouseout", function(d,i) {
tooltip.classed("hidden", true);
}); // end mouseout

} // end draw()

Giving us this sort of visualization [interactive web page]:

CYMH Service Areas 33 tooltipsr
Figure 4. Thirty-three Colour CYMH Service Areas in Ontario with Tooltips.

Next time: We’ll enhance the functionality of our visualization to allow the user to pan and zoom our map of the CYMH Service Areas in Ontario.

Visualizing the MCYS Service Areas within Integrated Service Regions Using D3.geo

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

In a previous posting, we described our method for partitioning the Shapefile archive (cymh_shapefile.zip cymh_service_areas_after_march_9_2015.zip) of the thirty-four thirty-three MCYS Children and Youth Mental Health Service Areas (CYMHSAs) into five groupings, corresponding to the MCYS Integrated Service Regions (ISRs). We also provided the GeoJSON and TopoJSON files for the individual CYMH Service Areas and their groupings into Integrated Service Regions.

Now we’ll illustrate how to use the TopoJSON files and d3.geo to visualize the CYMH Service Areas within their respective Integrated Service Regions.

In the template below,  we’ve highlighted in red any values that relate to the Integrated Service Region of interest and we’ve highlighted in blue any values that relate to the CYMH Service Areas within the Integrated Service Region:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

/* CSS goes here */

/* fill the Service Areas using colour scheme for their corresponding Integrated Service Region*/
.<ISR>_geo.<ServiceArea-1> { fill: <colour-1>; }
.<ISR>_geo.<ServiceArea-2> { fill: <colour-2>; }
...
.<ISR>_geo.<ServiceArea-n> { fill: <colour-n>; }

/* style the Service Area boundaries */
.sa_boundary {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
  stroke-linejoin: round;
}

/* style the Service Area labels */

.area-label {
 fill: #000;
 fill-opacity: .9;
 font-size: 10px;
 text-anchor: middle;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src= "//d3js.org/topojson.v1.min.js"></script>

<script>

/* 1. Set the width and height (in pixels) of the canvas */
var width = 960,
    height = 500;
 
/* 2. Create an empty root SVG element */

var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height);

/* 3. Define the Unit projection to project 3D spherical coordinates onto the 2D Cartesian plane.Note - we use the Albers equal-area conic projection. */
var projection = d3.geo.albers()
    .scale(1)
    .translate([0, 0]);

/* 4. Define the path generator - to format the projected 2D geometry for SVG */
var path = d3.geo.path()
    .projection(projection);

/* 5.0 Open the d3.json callback, and
/* 5.1 Load the TopoJSON data file. */

d3.json("<ISR>_topo.json", function(error, <ISR>_topo) {
if (error) return console.error(error);

/* 5.2 Convert the TopoJSON data back to GeoJSON format */

  var areas_var = topojson.feature(<ISR>_topo, <ISR>_topo.objects.<ISR>_geo);
/* 5.2.1 Calculate new values for scale and translate using bounding box of the service areas */
 
var b = path.bounds(areas_var);
var s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

/* 5.2.2 New projection, using new values for scale and translate */
projection
   .scale(s)
   .translate(t);

/* 5.3 Bind the GeoJSON data to the path element and use selection.attr to set the "d" attribute to the path data */

svg.append("path")
.datum(areas_var)
.attr("d", path);

/* 6. Draw the boundaries of the Service Areas */
  svg.append("path")
      .datum(topojson.mesh(<ISR>_topo, <ISR>_topo.objects.<ISR>_geo, function(a, b) { return a !== b; }))
      .attr("class", "sa_boundary")
      .attr("d", path);

/* 7 Colour the Service Areas */

  svg.selectAll(".<ISR>_geo")
      .data(topojson.feature(<ISR>_topo, <ISR>_topo.objects.<ISR>_geo).features)
      .enter().append("path")
      .attr("class", function(d) { return "<ISR>_geo " + d.id; })
      .attr("d", path);

/* 8 Label the Service Areas */

 svg.selectAll(".area-label")
 .data(topojson.feature(<ISR>_topo, <ISR>_topo.objects.<ISR>_geo).features)
 .enter().append("text")
 .attr("class", function(d) { return "area-label " + d.id; })
 .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
 .attr("dy", ".35em")
 .text(function(d) { return d.properties.area_name; });

/* 9. Close the d3.json callback */

});

</script>

The following table presents the five MCYS Integrated Service Regions and their respective CYMH Service Areas. Drawing upon the resources of ColorBrewer, we’ve assigned a different hue to every Integrated Service Region and a distinctive colour of that hue to every member CYMH Service Area:

Central Region
Service Area Colour
Dufferin/Wellington #fcbba1
Halton #fc9272
Peel #fb6a4a
Simcoe #ef3b2c
Waterloo #fee0d2
York #a50f15
East Region
Service Area Colour
Durham #efedf5
Frontenac/Lennox and Addington #9e9ac8
Haliburton/Kawartha Lakes/Peterborough #dadaeb
Hastings/Prince Edward/Northumberland #bcbddc
Lanark/Leeds and Grenville #807dba
Ottawa #6a51a3
Prescott and Russell #54278f
Renfrew #54278f
Stormont, Dundas and Glengarry #3f007d
North Region
Service Area Colour
Algoma #74c476
Greater Sudbury/Manitoulin/Sudbury #a1d99b
James Bay Coast #238b45
Kenora/Rainy River #00441b
Nipissing/Parry Sound/Muskoka #c7e9c0
Thunder Bay #006d2c
Timiskaming/Cochrane

Cochrane/Timiskaming (including James Bay Coast)

#41ab5d
Toronto Region
Service Area Colour
Toronto #f16913
West Region
Service Area Colour
Brant #08519c
Chatham-Kent #c6dbef
Elgin/Oxford #4292c6
Essex #deebf7
Grey/Bruce #08519c
Haldimand-Norfolk #2171b5
Hamilton #08306b
Huron/Perth #2171b5
Lambton #9ecae1
Middlesex #6baed6
Niagara #4292c6

So, now let’s display the Integrated Service Regions and their member CYMH Service Areas:

Central Region (actual rendering):

MCYS Central Region and Member CYMH Service Areas
Figure 1. MCYS Central Region and Member CYMH Service Areas.

East Region (actual rendering):

MCYS Central Region and Member CYMH Service Areas
Figure 2. MCYS Central Region and Member CYMH Service Areas.

Toronto Region (actual rendering):

MCYS Toronto Region
Figure 3. MCYS Toronto Region.

North Region – 7 Service Areas (actual rendering):

MCYS North Region and Member CYMH Service Areas
Figure 4a. MCYS North Region and 7 Member CYMH Service Areas.

North Region – 6 Service Areas (actual rendering):

CYMH Service Areas in North Region - 33 - screenshot
Figure 4b. MCYS North Region and 6 Member CYMH Service Areas.

West Region (actual rendering):

MCYS West Region and Member CYMH Service Areas
Figure 5. MCYS West Region and Member CYMH Service Areas.

Next time: We’ll add some functionality so that users can interact with our maps.

MCYS Service Areas and Integrated Service Regions in GeoJSON and TopoJSON Formats

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

Here we provide geospatial data for the MCYS Integrated Service Regions and their constituent Children and Youth Mental Health Service Areas in GeoJSON and TopoJSON file formats:

Central Region GeoJSON TopoJSON
Dufferin/Wellington GeoJSON TopoJSON
Halton GeoJSON TopoJSON
Peel GeoJSON TopoJSON
Simcoe GeoJSON TopoJSON
Waterloo GeoJSON TopoJSON
York GeoJSON TopoJSON
East Region GeoJSON TopoJSON
Durham GeoJSON TopoJSON
Frontenac/Lennox and Addington GeoJSON TopoJSON
Haliburton/Kawartha Lakes/Peterborough GeoJSON TopoJSON
Hastings/Prince Edward/Northumberland GeoJSON TopoJSON
Lanark/Leeds and Grenville GeoJSON TopoJSON
Ottawa GeoJSON TopoJSON
Prescott and Russell GeoJSON TopoJSON
Renfrew GeoJSON TopoJSON
Stormont, Dundas and Glengarry GeoJSON TopoJSON
North Region – 7 Service Areas

North Region – 6 Service Areas

GeoJSON

GeoJSON

TopoJSON

TopoJSON

Algoma GeoJSON TopoJSON
Greater Sudbury/Manitoulin/Sudbury GeoJSON TopoJSON
James Bay Coast GeoJSON TopoJSON
Kenora/Rainy River GeoJSON TopoJSON
Nipissing/Parry Sound/Muskoka GeoJSON TopoJSON
Thunder Bay GeoJSON TopoJSON
Timiskaming/Cochrane

Cochrane/Timiskaming (including James Bay Coast)

GeoJSON

GeoJSON

TopoJSON

TopoJSON

Toronto Region GeoJSON TopoJSON
West Region GeoJSON TopoJSON
Brant GeoJSON TopoJSON
Bruce/Grey GeoJSON TopoJSON
Chatham-Kent GeoJSON TopoJSON
Elgin/Oxford GeoJSON TopoJSON
Essex GeoJSON TopoJSON
Haldimand-Norfolk GeoJSON TopoJSON
Hamilton GeoJSON TopoJSON
Huron/Perth GeoJSON TopoJSON
Lambton GeoJSON TopoJSON
Middlesex GeoJSON TopoJSON
Niagara GeoJSON TopoJSON

Geospatial features of the MCYS Children and Youth Mental Health Service Areas

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

In 2014-15, the Ministry of Children and Youth Services (MCYS) defined two administrative views of mental health services for children and youth in Ontario:

The provincial government has published geospatial data for the MCYS’s Integrated Service Regions (ISRs) and Children and Youth Mental Health Service Areas (CYMHSAs) in Shapefile format.

Here, we’ll work only with the geospatial data for the CYMHSAs, publishing three sorts of files for use in d3.geo:

  1. Converting the Shapefile archive (cymh_shapefile.zip cymh_service_areas_after_march_9_2015.zip) for the entire set of thirty-four MCYS Children and Youth Mental Health Service Areas into a single TopoJSON file (cymhsas_topo.json)
  2. Partitioning the Shapefile archive in #1 into five groups of Service Areas, corresponding to the Integrated Service Regions, and converting these five groups into TopoJSON files:
    1. central_topo.json
    2. east_topo.json
    3. north_topo.json
    4. toronto_topo.json
    5. west_topo.json
  3. Partitioning the Shapefile archive in #1 into thirty-four thirty-three groups, corresponding to the individual MCYS Children and Youth Mental Health Service Areas, and converting these groups into TopoJSON files

Shapefile archive for 34 33 CYMHSAs

The Shapefile archive  for the thirty-four thirty-three MCYS CYMHSAs (cymh_service_areas_after_march_9_2015.zip) contains four files:

  • CYMH Service Areas.shp — shape format
  • CYMH Service Areas.shx — shape index format
  • CYMH Service Areas.dbf — attribute format
  • CYMH Service Areas.prj — projection format: the coordinate system and projection information, expressed in well-known text format

we rename the four CYMH Service Areas.* files cymh-service-areas.*

Converting the Shapefile archive to GeoJSON and TopoJSON format

To use d3.geo to visualize the CYMHSAs, we first use ogr2ogr to convert the Shapefiles to GeoJSON format, and then use topojson to convert the GeoJSON file to TopoJSON format:

ogr2ogr -t_srs EPSG:4269 -f GeoJSON cymhsas_geo.json cymh-service-areas.shp

topojson -o cymhsas_topo.json --id-property area_name --properties -- cymhsas_geo.json

Notes:

  • After running ogr2ogr, we use a text editor to replace the feature property Name with area_name in the file cymhsas_geo.json 1
  • The --id-property switch in topojson is used to promote the feature property area_name to geometry id in the file cymhsas_topo.json
  • We use a text editor to remove any special characters (e.g. spaces, “,”, “/”, “-“) from the value of the geometry id, e.g. “"id": "Haliburton/Kawartha Lakes/Peterborough"" becomes “"id": "HaliburtonKawarthaLakesPeterborough"” in cymhsas_topo.json

Partitioning the Shapefile archive of CYMHSAs into ISRs

We illustrate the partitioning of the Shapefile archive into groups of Children and Youth Mental Health Service Areas corresponding to the five Integrated Service Regions with the script for the North Region.
For 34 CYMHM Service Areas:

ogr2ogr -t_srs EPSG:4269 -f GeoJSON -where "Name =  'Algoma' OR Name = 'Greater Sudbury/Manitoulin/Sudbury' OR Name = 'James Bay Coast' OR Name = 'Kenora/Rainy River'  OR Name = 'Nipissing/Parry Sound/Muskoka' OR Name = 'Thunder Bay' OR Name =  'Timiskaming/Cochrane'" north_geo.json cymh-Service-Areas

topojson -o north_topo.json --id-property area_name --properties -- north_geo.json

For 33 CYMH Service Areas:

ogr2ogr -t_srs EPSG:4269 -f GeoJSON -where "ServiceA00 =  'Algoma' OR Name = 'Greater Sudbury/Manitoulin/Sudbury' OR Name = 'Kenora/Rainy River'  OR Name = 'Nipissing/Parry Sound/Muskoka' OR Name = 'Thunder Bay' OR Name =  'Cochrane/Timiskaming'" north_geo.json cymh-service-areas.shp

topojson -o north_topo.json --id-property area_name --properties -- north_geo.json

Note:

  • The MCYS uses various spelling conventions for compound CYMHSAs; the authoritative list of CYMHSAs naming conventions is found in CYMH-Service-Areas.dbf in the Shapefile archive.

Partitioning the Shapefile archive of CYMHSAs into individual CYMHSAs

Partitioning of the Shapefile archive into individual Children and Youth Mental Health Service Areas is straightforward, e.g.:

ogr2ogr -t_srs EPSG:4269 -f GeoJSON -where "Name = 'Toronto'" toronto_geo.json cymh-service-areas.shp

topojson -o toronto_topo.json --id-property area_name --properties -- toronto_geo.json

I’ve made a complete set of these GeoJSON and TopoJSON available for anyone to use freely.

 

 

Geospatial Features of the MCYS Integrated Service Regions

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

In 2014-15, the Ministry of Children and Youth Services (MCYS) defined two administrative views of mental health services for children and youth in Ontario:

The provincial government has published geospatial data for the MCYS’s Integrated Service Regions (ISRs) and Children and Youth Mental Health Service Areas (CYMHSAs) in Shapefile format. Here, we’ll work only with the geospatial data for the ISRs.

Shapefile format

The Shapefile archive for the ISRs (mcys_integrated_regions.zip) contains four files:

  • mcys_integrated_regions.shp — shape format
  • mcys_integrated_regions.shx — shape index format
  • mcys_integrated_regions.dbf — attribute format
  • mcys_integrated_regions.prj — projection format: the coordinate system and projection information, expressed in well-known text format

For ease of reference, we rename the four mcys_integrated_regions.* files isrs.*.

Converting Shapefiles to GeoJSON format

To use d3.geo to visualize the ISRs, we first convert the Shapefiles to GeoJSON format files, using ogr2ogr. There are three steps:

  1. Determine the Spatial Reference System (SRS) used by the Shapefile
  2. Set the -t_srs switch in ogr2ogr to output the GeoJSON file using this SRS
  3. Rename variables for ease of use

The projection format file for the ISRs specifies:

GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]

We use Prj2EPSG, a simple online service to convert the projection information contained in the .prj file into standard EPSG codes for the corresponding spatial reference system. From this we determine that the specification contained in isrs.prj corresponds to EPSG 4269 – GCS_North_American_1983.

We now use the -t_srs switch in ogr2ogr to transform the output using the spatial reference system specified in isrs.prj:

ogr2ogr -t_srs EPSG:4269 -f GeoJSON isrs_geo.json isrs.shp

The GeoJSON format file is isrs_geo.json.

Finally, we use a text editor to give more meaningful names to a few variables in the GeoJSON files and to express them in all lowercase letters:

Original variable Modified variable
Region region_name
Order order

Converting GeoJSON files to TopoJSON format

We use topojson to convert the GeoJSON file isrs_geo.json to a TopoJSON format file:

topojson -o isrs_topo.json --id-property region_name --properties -- isrs_geo.json

The --id-property switch in topojson is used to promote the feature property "region_name" to geometry id status in the TopoJSON file isrs_topo.json.

We may now visualize the MCYS Integrated Service Regions by applying d3.geo to isrs_topo.json.

Visualizing the MCYS Integrated Service Regions Using d3.geo

Preamble

This article was originally posted on May 14, 2016 and revised on July 28, 2016 to take account of changes in the geospatial representation of Children and Youth Mental Health Service Areas in Ontario. For more details, see … and then there were 33.

Introduction

In the past few years, a wide variety of free and open source software (FOSS) tools for visualizing geospatial data have become available.  For many people like me who work in human services, coming to know how to use these tools even in rudimentary ways represents a steep learning-curve. Here, I illustrate the use of one of these tools, d3.geo, to visualize a geospatial view of children and youth services in Ontario. 1

In 2014-15 the Ministry of Children and Youth Services (MCYS) defined two administrative views of Ontario:

The five Integrated Service Regions (ISRs) combined nine previous Service Delivery Division regions and four Youth Justice Services Division regions. The ISRs are integrated with the five regional boundaries of the Ministry of Community and Social Services (MCSS).

The thirty-four thirty-three Children and Youth Mental Health Service Areas (CYMHSAs) were defined after a thorough review, including an assessment of Statistics Canada’s census divisions and projected population and children and youth.

The Ontario government has published two Shapefile archives – mcys_integrated_regions.zip and cymh_shapefile.zip and cymh_service_areas_after_march_9_2015.zip – that define the geospatial boundaries of the ISRs and the CYMHSAs, respectively. For now, we’re going to work only with the Shapefile archive for the ISRs.

Before we can visualize the ISRs using d3.geo, we need to convert the Shapefile format archive – mcys_integrated_regions.zip - to a TopoJSON format file – isrs_topo.json. (For more details of converting geospatial data from one file format to another, see Geospatial Features of the MCYS Integrated Service Regions).

A Simple Map

So, let’s use d3.geo to visualize the MCYS Integrated Service Regions in Ontario.

HTML template

In the same directory as the isrs_topo.json file, we create a file – isrs01.html – using the following template:


<!DOCTYPE html>
<meta charset="utf-8">
<style>

/* CSS goes here */

</style>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src= "//d3js.org/topojson.v1.min.js"></script>

/*                                                           */
<script>
/* JavaScript for reading and rendering data goes here */
</script>

d3 supports the two main standards for rendering two-dimensional geometry in a browser: SVG and Canvas. We prefer SVG because you can style SVG using CSS, and declarative styling is easier.

There are several steps involved in reading and rendering our data in SVG:

  1. Define the width and height (in pixels) of the canvas
  2. Create an (empty) root SVG element
  3. Define the projection, beginning with a “unit projection” with .scale(1) and .translate([0,0])
  4. Define the path generator
  5. Open the d3.json callback
    1. Load the TopoJSON data file
    2. Convert the TopoJSON data back to GeoJSON format
    3. Calculate new values for .scale() and .translate() to resize and centre the projection
    4. Bind the GeoJSON data to the path element and use selection.attr to set the “d” attribute to the path data
  6. Maybe do some other stuff
  7. Close the d3.json callback

If we modify our template – isrs01.html – by adding the Javascript to load and render isrs_topo.json in SVG, we obtain:


<!DOCTYPE html>
<meta charset="utf-8">
<style>

/* CSS goes here */

</style>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src= "//d3js.org/topojson.v1.min.js"></script>

<script>

/* 1. Set the width and height (in pixels) of the canvas */
var width = 960,
    height = 1160;
 
/* 2. Create an empty root SVG element */

var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height);

/* 3. Define the Unit projection to project 3D spherical coordinates onto the 2D Cartesian plane - HERE we use the Albers equal-area conic projection. */
var projection = d3.geo.albers()
    .scale(1)
    .translate([0, 0]);

/* 4. Define the path generator - to format the projected 2D geometry for SVG */
var path = d3.geo.path()
    .projection(projection);

/* 5.0 Open the d3.json callback, and
/* 5.1 Load the TopoJSON data file. */

d3.json("isrs_topo.json", function(error, isrs_topo) {
if (error) return console.error(error);

/* 5.2 Convert the TopoJSON data back to GeoJSON format */

  var regions_var = topojson.feature(isrs_topo, isrs_topo.objects.isrs_geo);
/* 5.2.1 Calculate new values for scale and translate using bounding box of the service areas */
 
var b = path.bounds(regions_var);
var s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

/* 5.2.2 New projection, using new values for scale and translate */
projection
   .scale(s)
   .translate(t);

/* 5.3 Bind the GeoJSON data to the path element and use selection.attr to set the "d" attribute to the path data */

svg.append("path")
.datum(regions_var)
.attr("d", path);

/* 6 - 8 Some other stuff TBD later */

/* 9. Close the d3.json callback */

});

</script>

… which gives us this sort of basic rendering of the MCYS Integrated Service Regions [actual rendering]:

Figure 1. Basic rendering of the MCYS Integrated Service Regions.
Figure 1. Basic rendering of the MCYS Integrated Service Regions.

There are a few obvious improvements we can make. First, let’s draw the boundaries of the MCYS ISRs:


/* CSS goes here */

/* Define the boundary of an ISR as a 1.5 px wide white line, with a round line-join */
.isr_boundary {
  fill: none;
  stroke: #fff;
  stroke-width: 1.5px;
  stroke-linejoin: round;
}

...

/* Javascript for reading and rendering data in SVG */

...

/* 6. Draw the boundaries of the ISRs */
  svg.append("path")
      .datum(topojson.mesh(isrs_topo, isrs_topo.objects.isrs_geo, function(a, b) { return a !== b; }))
      .attr("class", "isr_boundary")
      .attr("d", path);

… giving us this sort of map [actual rendering]:

MCYS Integrated Service Regions with boundaries
Figure 2. Rendering of the MCYS Integrated Service Regions with boundaries.

… and then let’s label and colour the MCYS ISRs using the colour-scheme adopted by the MCYS:


/* CSS goes here */

/* fill the ISRs using the MCYS colour scheme */
.isrs_geo.Toronto { fill: #bd3f23; }
.isrs_geo.Central { fill: #fcb241; }
.isrs_geo.East { fill: #a083a7; }
.isrs_geo.West { fill: #e3839e; }
.isrs_geo.North { fill: #8dc73d; }

/* switch the colour of the ISR boundaries to black */
.isr_boundary {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
  stroke-linejoin: round;
}

/* style the Region label */

.region-label {
 fill: #000;
 fill-opacity: .9;
 font-size: 12px;
 text-anchor: middle;
}

...

/* Javascript for reading and rendering data in SVG */

...

/* 7 Colour the ISRs */

  svg.selectAll(".isrs_geo")
      .data(topojson.feature(isrs_topo, isrs_topo.objects.isrs_geo).features)
      .enter().append("path")
      .attr("class", function(d) { return "isrs_geo " + d.id; })
      .attr("d", path);

/* 8 Label the Integrated Service Regions */

 svg.selectAll(".region-label")
 .data(topojson.feature(isrs_topo, isrs_topo.objects.isrs_geo).features)
 .enter().append("text")
 .attr("class", function(d) { return "region-label " + d.id; })
 .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
 .attr("dy", ".35em")
 .text(function(d) { return d.properties.region_name; });

giving us this sort of map [actual rendering]:

Figure 3. Labelling and rendering of the MCYS Integrated Service Regions in colour.
Figure 3. Labeling and rendering of the MCYS Integrated Service Regions in colour.

Wrap-Up

In this post, we use d3.geo – a free and open source software tool – to visualize a publicly-available geospatial dataset related to children and youth services in five regions across Ontario. Next time, we will use another dataset to visualize children and youth services at the level of thirty-four service areas in the province.

  1. Accessing d3.geo is easy – you simply include a single call to d3 in the body of an .html web page. Installing and using some of the tools for converting geospatial data from one format to another (in order to use d3.geo) is more complicated. For some more technical details, see  Installing tools for d3.geo – 20160306.

Installing tools for d3.geo – 20160306

In Let’s make a map, Mike Bostock describes how to make a modest map from scratch using D3 and TopoJSON. Here we detail how to install the main tools on our CentOS 6x server.

Installing Tools

Geographic data files are almost always too large for manual cleanup or conversion. Fortunately, there’s a vibrant geo open-source community, and many excellent free tools to manipulate and convert between standard formats.

GDAL

The big multitool to know is the Geospatial Data Abstraction Library. Commonly referred to as GDAL, it includes the OGR Simple Features Library and the ogr2ogr binary we’ll use to manipulate shapefiles. There are official GDAL binaries for a variety of platforms – our hosted service runs on CentOS 6x.

The Enterprise Linux GIS (ELGIS) effort provides RPMs of various GIS applications, including GDAL, for CentOS and other Enterprise Linux derivatives. To upload the release RPM for CentOS 6x:

sudo rpm -Uvh http://elgis.argeo.org/repos/6/elgis-release-6-6_0.noarch.rpm

To install GDAL:

sudo yum install -y gdal

… but this generates a lot of dependency errors. In the end, the most significant issue we had to address was GDAL requirement for armadillo-3x instead of the newer (and not backward-compatible vis-a-vis GDAL) armadillo-4x.

We tracked down a copy of armadillo-3.800.2-1.el6.src.rpm, uploaded it to our /root directory, and installed:

sudo rpm -Uvh armadillo-3.800.2-1.el6.x86_64.rpm

… and then we were able to install the GDAL RPM package, as above.

Miscellaneous things we did along the way to installing GDAL

While we’re uncertain of their ultimate significance, we installed/compiled some resources that are worth noting:

Some of the missing dependencies that were flagged up to us were addressed by installing two packages:

su -c 'rpm -Uvh http://mirror.centos.org/centos/6/os/x86_64/Packages/atlas-3.8.4-2.el6.x86_64.rpm

su -c 'rpm -Uvh http://dl.fedoraproject.org/pub/epel/6//x86_64/arpack-3.1.3-1.el6.x86_64.rpm'

We also compiled proj4 and geos:

wget ftp://ftp.remotesensing.org/proj/proj-4.6.0.tar.gz
tar -zxvf proj-4.6.0.tar.gz
cd proj-4.6.0
./configure
sudo make install

cd ..
wget http://geos.refractions.net/downloads/geos-3.0.0.tar.bz2
tar -jxvf geos-3.0.0.tar.bz2
cd geos-3.0.0
./configure
sudo make install
# add lib path to ld.so.conf file
sudo vi /etc/ld.so.conf
# add this line
/usr/local/lib
sudo /sbin/ldconfig
# Add lib path to ld.so.conf file
sudo vi /etc/ld.so.conf
# add this line
/usr/local/lib
sudo /sbin/ldconfig

TopoJSON

Next you’ll need the reference implementation for TopoJSON, which requires Node.js. Fortunately, we’d already arranged for our host to install Node.js. To install TopoJSON:

npm install -g topojson

… which throws a warning: {several modules} requires inherits@’2′ but will load – even after we install pm2:

npm install pm2 -g

[note: when we were trying to merge shp files, threw error that someone suggested would be fixed by uninstalling topojson and re-installing with sudo -H npm install -g topojson]

To check the installation:

which ogr2ogr
# prints /usr/local/bin/ogr2ogr
which topojson
# prints /usr/local/bin/topojson

A Vocabulary of Government Service – Part I

Previously we described the inheritance hierarchy of Classes in Schema.org and visualized this hierarchy as an expandable/collapsible tree using d3.

Now we build upon that work to develop a vocabulary of Classes and their Properties for describing government service.

Seeding the Vocabulary

The starting point for seeding our vocabulary is Schema.org’s Class GovernmentService, used to describe a service that is provided by a government organization or by an organization that is funded by government.

Figure 1 illustrates the pathway to Class GovernmentService within Schema.org’s Inheritance Hierarchy.

Figure 1. Pathway to GovernmentService through Schema.org.

Class GovernmentService has one Property – serviceOperator that is expected to be of Type Organizationanother Class in Schema.org. GovernmentService is the Domain of serviceOperator and Organization is its Range.

Schema.org’s website represents the above in the form of a Table:

Properties from GovernmentService
Property Range Description
serviceOperator Organization The operating organization, if different from the provider. This enables the representation of services that are provided by an organization, but operated by another organization like a subcontractor.

Table 1. Properties of Class GovernmentService.

We may also represent the information in Table 1 as a Graph, where the Nodes are Classes and Properties, and where the Links are relations connecting them:

Source Node Target Node Link
GovernmentService serviceOperator hasProperty
serviceOperator Organization hasRange

Table 2. Graph of vocabulary for describing service that is provided by a government organization.

Extending the Vocabulary – Cycle 1

This start on a vocabulary for describing government service may be extended in a systematic fashion – first, by incorporating any SuperClass (and its Properties) that contains GovernmentService as a Subclass.

In this manner, our vocabulary extends to include Class Service, Intangible, and Thingas well as their respective Properties. (Note that these Classes are the points highlighted along the pathway in Figure 1).

Again, Schema.org’s website represents each of these SuperClasses in the form of a Table:

Properties from Service
Property Range Description
availableChannel ServiceChannel A means of accessing the service (e.g. a phone bank, a web site, a location, etc.)
produces Thing The tangible thing generated by the service, e.g. a passport, permit, etc.
provider Person  or
Organization
The service provider, service operator, or service performer; the goods producer. Another party (a seller) may offer those services or goods on behalf of the provider. A provider may also serve as the seller.
serviceArea AdministrativeArea The geographic area where the service is provided.
serviceAudience Audience The audience eligible for this service.
serviceType Text The type of service being offered, e.g. veterans’ benefits, emergency relief, etc.

Table 3.1. Properties of Class GovernmentService that are inherited from Class Service.

and

Properties from Thing
Property Range Description
additionalType URL An additional type for the item, typically used for adding more specific types from external vocabularies in microdata syntax. This is a relationship between something and a class that the thing is in. In RDFa syntax, it is better to use the native RDFa syntax – the ‘typeof’ attribute – for multiple types. Schema.org tools may have only weaker understanding of extra types, in particular those defined externally.
alternateName Text An alias for the item.
description Text A short description of the item.
image URL  or
ImageObject
An image of the item. This can be a URL or a fully described ImageObject.
name Text The name of the item.
potentialAction Action Indicates a potential Action, which describes an idealized action in which this thing would play an ‘object’ role.
sameAs URL URL of a reference Web page that unambiguously indicates the item’s identity. E.g. the URL of the item’s Wikipedia page, Freebase page, or official website.
url URL URL of the item.

Table 3.2. Properties of Class GovernmentService that are inherited from Class Thing.

Class Intangible has no Properties of its own – all of its Properties are inherited from Class Thing.

At the end of Cycle 1 of extending the vocabulary, our Graph is looking much more respectable (compared to Table 1):

At the end of Cycle 1 of extending the vocabulary, our Graph has become much richer (compared to Table 1):

Source Node Target Node Relation
Thing Intangible hasSubclass
Intangible Service hasSubclass
Service GovernmentService hasSubclass
Thing additionalType hasProperty
Thing alternateName hasProperty
Thing description hasProperty
Thing image hasProperty
Thing name hasProperty
Thing potentialAction hasProperty
Thing sameAs hasProperty
Thing url hasProperty
Service availableChannel hasProperty
Service produces hasProperty
Service provider hasProperty
Service serviceArea hasProperty
Service serviceAudience hasProperty
Service serviceType hasProperty
GovernmentService serviceOperator hasProperty
additionalType URL hasRange
alternateName Text hasRange
availableChannel ServiceChannel hasRange
description Text hasRange
image ImageObject hasRange
image URL hasRange
name Text hasRange
potentialAction Action hasRange
produces Thing hasRange
provider Organization hasRange
provider Person hasRange
sameAs URL hasRange
serviceArea AdministrativeArea hasRange
serviceAudience Audience hasRange
serviceOperator Organization hasRange
serviceType Text hasRange
url URL hasRange

Table 4. Graph of vocabulary for describing service that is provided by a government organization (Cycle 1).

We may serialize the Graph in Table 4 using various semantic technologies, including RDF/XML, RDFa, and Turtle.

Pruning

Note in Table 4 that Property image may be of type URL or ImageObject; here we’re going to use only “cool” URLs – both for the sake of having a persistent identifier for an image that may be modified from time to time and to avoid introducing the clutter of a complex entity like ImageObject – which is incidental to the semantics of a government service – into our vocabulary.

Also note in Table 4 that Property provider may be of type Organization or Person; here we’re going to restrict ourselves to providers of government service that are organizations and not individuals. We will bring Class Person (e.g. as an employee of an organization) into our vocabulary in a subsequent Cycle.

Visualizing

In a fairly traditional manner, our vocabulary for GovernmentService may be visualized as a basic Class Diagram using the Unified Modeling Language (UML):

Figure 2. Visualization of Vocabulary for GovernmentService (Cycle 1) using a UML Class Diagram.

In a more innovative fashion, we may also visualize our vocabulary GovernmentService as a Force-Directed Graph (with Thing, Intangible, Service and GovernmentService fixed in position in the corners of the graph:

Figure 3. Visualization of Graph of GovernmentService (Cycle 1), where o = Property, D = Domain, and R = Range.

See also this interactive version of Figure 3.

Note in Table 4 that several Properties are of type Text or URL – Schema.org treats Text, URL and a few other entities (Boolean, Date, DateTime, Number, Time) as a Datatype (as opposed to a Thing). We may streamline the visualization of our vocabulary by terminating any node corresponding to one of these Properties with a colored-symbol specific to its Datatype:

Figure 4. Legend for terminating a Property node whose Range is Datatype.

Here’s our streamlined visualization of our vocabulary for GovernmentService:

Figure 5. Visualization of Graph of GovernmentService (Cycle 1) using D3, where o = Property, D = Domain, and R = Range, terminating Property nodes with Range = Datatype.

See also this interactive version of Figure 5.

Coming Up:

A Vocabulary of Government Service – Part II

Part III: The Architecture of Service: the Service Organization and Service Channel

Part IV: The Service Audience and Administrative Area

Part V: The Service Action

A Vocabulary of Government Service – Part II

A Second Cycle of Developing a Vocabulary of Government Service

At the end of our first cycle of developing a vocabulary of government service, we had arrived at the following Graph:

Source Node Target Node Relation
Schema Thing hasSubclass
Thing Intangible hasSubclass
Intangible Service hasSubclass
Service GovernmentService hasSubclass
Thing additionalType hasProperty
Thing alternateName hasProperty
Thing description hasProperty
Thing image hasProperty
Thing name hasProperty
Thing potentialAction hasProperty
Thing sameAs hasProperty
Thing url hasProperty
Service availableChannel hasProperty
Service produces hasProperty
Service provider hasProperty
Service serviceArea hasProperty
Service serviceAudience hasProperty
Service serviceType hasProperty
GovernmentService serviceOperator hasProperty
additionalType URL hasRange
alternateName Text hasRange
availableChannel ServiceChannel hasRange
description Text hasRange
image URL hasRange
name Text hasRange
potentialAction Action hasRange
produces Thing hasRange
provider Organization hasRange
sameAs URL hasRange
serviceArea AdministrativeArea hasRange
serviceAudience Audience hasRange
serviceOperator Organization hasRange
serviceType Text hasRange
url URL hasRange

Table 1. Graph of a vocabulary of government service (Cycle 1).

Our second cycle through Schema.org to enrich  our vocabulary further looks to incorporate fully any Class that had defined the Range of some Property at the end of Cycle 1.  There are fifteen rows  in Table 1 where Relation = hasRange – though there are only eight unique Classes (URL, Text, ServiceChannel, Action, Thing, OrganizationAdministrativeArea, and Audience) occupying the Target Node.

Figure 1 illustrates our initial pathway from Schema -> Thing -> Intangible -> Service -> GovernmentService within Schema.org  – as well as the positions of these eight additional Classes within the Inheritance Hierarchy:

GovernmentService Classes at end of Cycle 1

Figure 1. Initial pathway from Schema -> Thing -> Intangible – > Service -> Government Service plus the position of Classes that defined the Range of Properties of Classes along this initial pathway.

These eight additional Classes fall into three categories:

  1. Classes that are included already in the vocabulary (e.g. Thing).
  2. Classes that are datatypes (e.g.  URL, Text) and whose inclusion would add no new Properties to the vocabulary.
  3. Classes that represent new entities (e.g. ServiceChannel, Action, OrganizationAdministrativeArea, and Audience) and whose inclusion would add new Properties to the vocabulary.

Only the third sort of Class offers an avenue for enriching our vocabulary.

Let’s take Class ServiceChannel as an example of how we want to proceed:

The first step is to take account of ServiceChannel’s position in Schema.org’s hierarchy of Classes. On its website, Schema.org asserts the equivalent of:

  • Thing, Intangible, hasSubclass
  • Intangible, ServiceChannel, hasSubclass

Here we note that the first assertion is already part of the vocabulary (Table 4 – Row 1); however, the second assertion is not and its addition to our Graph would enhance our vocabulary.

The second step is to take account of the Properties of Class ServiceChannel:

Properties from Class ServiceChannel
Property Range Description
availableLanguage Language A language someone may use with the item.
processingTime Duration Estimated processing time for the service using this channel.
providesService Service The service provided by this channel.
serviceLocation Place The location (e.g. civic structure, local business, etc.) where a person can go to access the service.
servicePhone ContactPoint The phone number to use to access the service.
servicePostalAddress PostalAddress The address for accessing the service by mail.
serviceSmsNumber ContactPoint The number to access the service by text message.
serviceUrl URL The website to access the service.

Table 2. Properties of Class ServiceChannel.

These eight Properties (availableLanguage, processingTime, providesService, serviceLocation, servicePhone, servicePostalAddress, serviceSmsNumber, serviceUrl) of Class ServiceChannel are new and so will be added to our vocabulary. Note that Class ServiceChannel also inherits all of the Properties of its superordinate Class Thing – but that these Properties are already included in our vocabulary and do not represent an opportunity for enhancement.

The third and final step is to take account of the Ranges of Class ServiceChannel‘s Properties – thereby adding five Classes (Language, Duration, Place, ContactPoint, and PostalAddress) to our vocabulary – (note that Class Service and Class URL are already included).

Quantitative Impact on Vocabulary

We may quantify the impact of adding any Class (ServiceChannel, Action, OrganizationAdministrativeArea, and Audience) to our vocabulary in Cycle 2 by using our vocabulary at the end Cycle 1 as a baseline:

  1. How many unique assertions of the form “Node_iNode_j, hasSubclass” are associated with the Class and how many of them are new?
  2. How many unique assertions of the form “Node_iNode_j, hasProperty” are associated with the Class and how many of them are new?
  3. How many unique assertions of the form “Node_iNode_j, hasRange” are associated with the Class and how many of them are new?
  4. How many unique Classes are referenced in #1 – #3 above and how many of them are new?
  5. How many unique Properties are referenced in #1 – #3 above are how many of them are new?

In the case of Class ServiceChannel, we observe:

  • There are two assertions of the form “Node_iNode_j, hasSubclass” – one assertion is already included in the vocabulary at the end of Cycle 1; one assertion is new and would be an enhancement to the vocabulary.
  • There are fifteen unique assertions of the form “Node_iNode_j, hasProperty” – eight unique assertions that derive from Class Thing are already included in the vocabulary; eight assertions that derive from Class ServiceChannel itself are new and would be enhancements to the vocabulary.
  • There are twenty-one unique assertions of the form “Node_iNode_j, hasRange”; thirteen unique assertions are already included in the vocabulary; eight unique assertions are new and would be enhancements to the vocabulary.
  • There are nineteen unique Classes standing in form Node_i or Node_j in assertions of the form “Node_i,Node_j, hasSubclass”, or Node_i in assertions of the form “Node_i,Node_j, hasProperty”; five of these unique Classes (Language, Duration, Place, ContactPoint, PostalAddress) are new.
  • There are twenty-four unique Properties of the form Node_j in assertions of the form “Node_i,Node_j, hasProperty” – eight of these unique Properties are new.

Note that this method of enriching our vocabulary of government service depends entirely on the structure of Schema.org – there is no model of government service that comes into the exercise.

Applying steps #1 – #5 above to the other Classes that had defined the Range of some Property in Cycle 1, we observe the following impacts of adding these Classes individually or altogether to our vocabulary:

New Assertions New Nodes
 Added Range hasSubclass hasProperty hasRange Classes Properties
ServiceChannel 1 8 8 5 8
Action 1 11 13 6 11
Organization 1 33 39 15 33
AdministrativeArea 2 15 19 11 15
Audience 1 2 2 0 2
Altogether 6 69 69 25 58

Table 3. Introduction of new components into vocabulary for GovernmentService in Cycle 2.

The Graph of our vocabulary at the end of Cycle 2 includes 25 + 58 = 83 additional Nodes and 6 + 69 + 69 = 144 additional assertions about the relations between these Nodes and/or between these Nodes and the Nodes of our vocabulary at the end of Cycle 1:

Assertions included in Cycle 1
Source Node Target Node Relation
Thing Intangible hasSubClass
Intangible Service hasSubClass
Service GovernmentService hasSubClass
Thing additionalType hasProperty
Thing alternateName hasProperty
Thing description hasProperty
Thing image hasProperty
Thing name hasProperty
Thing potentialAction hasProperty
Thing sameAs hasProperty
Thing url hasProperty
Service availableChannel hasProperty
Service produces hasProperty
Service provider hasProperty
Service serviceArea hasProperty
Service serviceAudience hasProperty
Service serviceType hasProperty
GovernmentService serviceOperator hasProperty
additionalType URL hasRange
alternateName Text hasRange
availableChannel ServiceChannel hasRange
description Text hasRange
image URL hasRange
name Text hasRange
potentialAction Action hasRange
produces Thing hasRange
provider Organization hasRange
sameAs URL hasRange
serviceArea AdministrativeArea hasRange
serviceAudience Audience hasRange
serviceOperator Organization hasRange
serviceType Text hasRange
url URL hasRange
Assertions added in Cycle 2
Thing Action hasSubClass
Thing Organization hasSubClass
Thing Place hasSubClass
Intangible Audience hasSubClass
Intangible ServiceChannel hasSubClass
Place AdministrativeArea hasSubClass
Action actionStatus hasProperty
Action agent hasProperty
Action endTime hasProperty
Action error hasProperty
Action instrument hasProperty
Action location hasProperty
Action object hasProperty
Action participant hasProperty
Action result hasProperty
Action startTime hasProperty
Action target hasProperty
Audience audienceType hasProperty
Audience geographicArea hasProperty
Organization address hasProperty
Organization aggregateRating hasProperty
Organization brand hasProperty
Organization contactPoint hasProperty
Organization department hasProperty
Organization dissolutionDate hasProperty
Organization duns hasProperty
Organization email hasProperty
Organization employee hasProperty
Organization event hasProperty
Organization faxNumber hasProperty
Organization founder hasProperty
Organization foundingDate hasProperty
Organization foundingLocation hasProperty
Organization globalLocationNumber hasProperty
Organization hasPOS hasProperty
Organization interactionCount hasProperty
Organization isicV4 hasProperty
Organization legalName hasProperty
Organization location hasProperty
Organization logo hasProperty
Organization makesOffer hasProperty
Organization member hasProperty
Organization memberOf hasProperty
Organization naics hasProperty
Organization owns hasProperty
Organization producer hasProperty
Organization review hasProperty
Organization seeks hasProperty
Organization subOrganization hasProperty
Organization taxID hasProperty
Organization telephone hasProperty
Organization vatID hasProperty
Place address hasProperty
Place aggregateRating hasProperty
Place containedIn hasProperty
Place event hasProperty
Place faxNumber hasProperty
Place geo hasProperty
Place globalLocationNumber hasProperty
Place hasMap hasProperty
Place interactionCount hasProperty
Place isicV4 hasProperty
Place logo hasProperty
Place openingHoursSpecification hasProperty
Place photo hasProperty
Place review hasProperty
Place telephone hasProperty
ServiceChannel availableLanguage hasProperty
ServiceChannel processingTime hasProperty
ServiceChannel providesService hasProperty
ServiceChannel serviceLocation hasProperty
ServiceChannel servicePhone hasProperty
ServiceChannel servicePostalAddress hasProperty
ServiceChannel serviceSmsNumber hasProperty
ServiceChannel serviceUrl hasProperty
actionStatus ActionStatusType hasRange
address PostalAddress hasRange
agent Organization hasRange
agent Person hasRange
aggregateRating AggregateRating hasRange
audienceType Text hasRange
availableLanguage Language hasRange
brand Organization hasRange
brand Brand hasRange
contactPoint ContactPoint hasRange
containedIn Place hasRange
department Organization hasRange
dissolutionDate Date hasRange
duns Text hasRange
email Text hasRange
employee Person hasRange
endTime DateTime hasRange
error Thing hasRange
event Event hasRange
faxNumber Text hasRange
founder Person hasRange
foundingDate Date hasRange
foundingLocation Place hasRange
geo GeoCoordinates hasRange
geo GeoShape hasRange
geograhicArea AdministrativeArea hasRange
globalLocationNumber Text hasRange
hasMap Map hasRange
hasMap URL hasRange
hasPOS Place hasRange
instrument Thing hasRange
interactionCount Text hasRange
isicV4 Text hasRange
legalName Text hasRange
location PostalAddress hasRange
location Place hasRange
logo URL hasRange
logo ImageObject hasRange
makesOffer Offer hasRange
member Organization hasRange
member Person hasRange
memberOf Organization hasRange
memberOf ProgramMembership hasRange
naics Text hasRange
object Thing hasRange
openingHoursSpecification OpeningHoursSpecification hasRange
owns OwnershipInfo hasRange
owns Product hasRange
participant Organization hasRange
participant Person hasRange
photo Photograph hasRange
photo ImageObject hasRange
processingTime Duration hasRange
producer Person hasRange
providesService Service hasRange
result Thing hasRange
review Review hasRange
seeks Demand hasRange
serviceLocation Place hasRange
servicePhone ContactPoint hasRange
servicePostalAddress PostalAddress hasRange
serviceSmsNumber ContactPoint hasRange
serviceUrl URL hasRange
startTime DateTime hasRange
subOrganization Organization hasRange
target EntryPoint hasRange
taxID Text hasRange
telephone Text hasRange
vatID Text hasRange

Table 4. Graph of vocabulary for describing service that is provided by a government organization (Cycle 2).

Our vocabulary for describing a service provided by a government organization now looks something like this (interactive version here):

Schema.org GovernmentService Cycle 2

Figure 5. Visualization of Graph of GovernmentService (Cycle 2), where o = Property, D = Domain, and R = Range (end of Cycle 1) and o = Property and R = Range (end of Cycle 2), terminating Property nodes with Range = Datatype.

After only two cycles through Schema.org, we see that our vocabulary of government service is already threatening to become unwieldy – the number of assertions in our Graph has increased dramatically, and many of the assertions added in Cycle 2 are less clearly relevant to describing government service. Proceeding with ingesting additional Classes and Properties into our vocabulary, using this methodology in a third, fourth, fifth Cycle of development, is an interesting exercise, but increasingly unproductive for our purposes.

Moving forward, then, we will adopt a model of service to guide our development of a vocabulary of government service using Schema.org.

Coming Up:

Part III: The Architecture of Service: the Service Organization and Service Channel

Part IV: The Service Audience and Administrative Area

Part V: The Service Action