-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgeospc.html
454 lines (395 loc) · 20.1 KB
/
geospc.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
<!DOCTYPE html>
<html>
<head>
<title>VALCRI - DExDs for Statistical Process Control</title>
<meta charset="utf-8">
<link rel="stylesheet" href="style/spc.css" type="text/css"></link>
<link rel="stylesheet" href="style/spcmap.css" type="text/css"></link>
<link rel="stylesheet" href="style/tufte.css" type="text/css"></link>
<link rel="stylesheet" href="style/dexd.css" type="text/css"></link>
<script type="text/javascript" src="lib/d3_4_5_0.min.js"></script>
<script type="text/javascript" src="js/map.js"></script>
<script type="text/javascript" src="js/spc.js"></script>
</head>
<body>
<div class="loading">Loading ...</div>
<div class="spcMapFooter">
<input onclick="moveTodayBackward()" class="button spcMapFooterItem" type="button" value="backward"/>
<input onclick="moveTodayForward()" class="button spcMapFooterItem" type="button" value="forward"/>
<div class="spcMapFooterItem">Today is <span class="displayToday"></span></div>
</div>
<h2>Representing Signals Geographically</h2>
<p><a href="index.html">Click here to go home</a></p>
<p>We have used colour to represent a quantity (the population of an area) a characteristic of a place (the NPU).
Here we use colour to show signals that occur at the most recent data point in our temporal sequence of crime data - which we will refer to as 'today'.</p>
<p>In the first visualisation below, we use a simple mapping to start with - red is any signal over the mean and blue is any signal under the mean. The data span from January 2011 to December 2016 and 'today' is currently set to <span class="displayToday"></span>.</p>
<p>You can move the date <input onclick="moveTodayBackward()" class="button" type="button" value="backward"/> and <input onclick="moveTodayForward()" class="button" type="button" value="forward"/> one month at a time using these grey buttons.</p>
<p>
We have also added some buttons at the bottom right that will persist as you scroll.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
A tile map showing whether a signal has been triggered in a neighbourhood. Click on a neighbourhood to see its SPC chart. <div>The date is <span class="displayToday"></span>.</div>
<div class="spcColourOnlyMeta"></div>
<div class="spcColourOnly sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcColourOnly container geo" alt="An SPC chart"></div>
</div>
</figure>
<p>We can add information about the <i>type</i> of signal that occurred 'today' by varying the <i>shape</i> of symbols in the reporting areas in which signals occur.</p>
<p>Click the tiles in the tile map to see the SPC chart for any neighbourhood.
Remember to use the <input onclick="moveTodayBackward()" class="button" type="button" value="backward"/> and <input onclick="moveTodayForward()" class="button" type="button" value="forward"/> buttons to change the month that we consider to be 'today'.</p>
<p class="question">
Can you relate the symbols on the map to the signals detected 'today' through the SPC chart?<br/>
Can you find any geographic clusters?
</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
A tile map showing the type of signal that has been triggered in a neighbourhood.
<div>The date is <span class="displayToday"></span>.</div>
<div class="spcIconsMeta"></div>
<div class="spcIcons sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcIcons container geo" alt="An SPC chart"></div>
</div>
</figure>
<p>Let's compare these methods, and the extent to which they are useful, in maps of different sizes. The fist graphic remains more clear when rendered at a smaller size when compared to the icon version. This is demonstrated in the visualisations below. The colouring on the right is visible at the second smallest size, whereas the icons only remain clear until the third smallest size. However, neither are clear at the smallest size.</p>
<p>This demonstrates how different methods of representing signals can be used depending on the size of the visualisation, something we will discuss later on when we wish to show many maps simultaneously.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
Using colour (left), and colour and shape (right) to show information about signals in each reporting area in maps of different sizes. While the icons in the maps on the right convey more information, it's hard to detect the colours from the varied shapes, and difficult to discern the shapes in maps of smaller size.
</span>
<div class="multiViewContainer">
<div class="iconSizeExample multiViewChild" style="display: flex; flex-direction: column;">
<div class="containerWrapper" style="width: 100%; align-self: center;">
<div class="geoSpcColourOnly container geo" alt="An SPC chart"></div>
</div>
<div class="containerWrapper" style="width: 75%; align-self: center;">
<div class="geoSpcColourOnly container geo" alt="An SPC chart"></div>
</div>
<div class="containerWrapper" style="width: 50%; align-self: center;">
<div class="geoSpcColourOnly container geo" alt="An SPC chart"></div>
</div>
<div class="containerWrapper" style="width: 25%; align-self: center;" >
<div class="geoSpcColourOnly container geo" alt="An SPC chart" ></div>
</div>
</div>
<div class="iconSizeExample multiViewChild" style="display: flex; flex-direction: column;">
<div class="containerWrapper" style="width: 100%; align-self: center;">
<div class="geoSpcIcons container geo" alt="An SPC chart"></div>
</div>
<div class="containerWrapper" style="width: 75%; align-self: center;">
<div class="geoSpcIcons container geo" alt="An SPC chart"></div>
</div>
<div class="containerWrapper" style="width: 50%; align-self: center;">
<div class="geoSpcIcons container geo" alt="An SPC chart"></div>
</div>
<div class="containerWrapper" style="width: 25%; align-self: center;">
<div class="geoSpcIcons container geo" alt="An SPC chart"></div>
</div>
</div>
</div>
</figure>
<p>We can also use a simple mark to represent signals. Here we use a horizontal line to signify no signal, and a line tilted up (positive) or down (negative) to signify a signal.
We reinforce this with colour. One way in which we can take advantage of this approach is to remove the underlying map and show only the marks.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
Here we represent each region purely as a line.<br/>
We use a discrete mapping for angle - a small angle represents eight over the mean, whereas a large angle represents one over three SD.
<div>The date is <span class="displayToday"></span>.</div>
<div class="spcGlyphsMeta"></div>
<div class="spcGlyphs sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcGlyphs container geo" alt="An SPC chart" ></div>
</div>
</figure>
<p class="question">
Click the horizontal and angled lines in the map - try some coloured angled lines and some flat horizontal ones.<br/>
Can you relate these angled lines to the signals detected 'today' through the SPC chart?
</p>
<p>Rather than representing a discreet value with the angle, perhaps we can convey further information by using line angles for numeric information such as difference between most recent data point and its predecessor.
This continuous mapping allows us to see some subtle differences between regions that share the same signal. We can use this mark to further convey information for all neighbourhoods. If there is no signal, then we can show the difference between the value of the latest data point and the process mean. This allows the opportunity to see unexpected patterns in the data. Although for any neighbourhood without a signal, this could be considered noise caused by random fluctuations.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
Here angle represents the difference between the process mean and the mean of the signal. For neighbourhoods without a signal, the angle represents the difference between the value of the latest data point and the process mean.
<div>The date is <span class="displayToday"></span>.</div>
<div class="spcGlyphsAngleAsMeanMeta"></div>
<div class="spcGlyphsAngleAsMean sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcGlyphsAngleAsMean container geo" alt="An SPC chart" ></div>
</div>
</figure>
<p>We can add more information to the geographic representation of SPC (or SPC map) by representing the number of data points that exceed an defined signal length as the thickness of the line.
So the line appears thicker if, for example, we have a sequence of nine months with reported crime levels above the mean (8 for the signal + 1 extra), or two months with levels over three standard deviations (1 for the signal + 1 extra).
This allows us to see signals that continue to exhibit persistent negative or positive behaviour -- those that have not yet been addressed.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
The same chart as above but with the addition of representing the number of points exceeding the sequence required to trigger the detected signal as line thickness.
<div>The date is <span class="displayToday"></span>.</div>
<div class="spcGlyphsAngleAsMeanWidthAsCountMeta"></div>
<div class="spcGlyphsAngleAsMeanWidthAsCount sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcGlyphsAngleAsMeanWidthAsCount container geo" alt="An SPC chart" ></div>
</div>
</figure>
<p>So far we have only visualised a signal that occurred 'today', but what if we want to show some historical aspect or trends in the data?
We could use the regular spaces provided by our tile map to show tiny simplified SPC charts in each square.
Showing all of the detail of the SPC charts is likely to make them difficult to read, so we need to develop designs that abstract the key information and make this readable on our tiles.
We propose a 'trend grid' as an aggregated method of showing all of the signals in a chart in their geographic setting.
We divide the time points into five bins (columns). If a signal is detected in a bin then a small box is drawn in that column. Its row is determined by the type of signal. Signals under the mean are drawn in the bottom half in blue, and signals above are drawn in the top half in red.
The further away the signal is from the mean, the further away from the centre point it is drawn. If a bin contains more than one type of signal then we see multiple entries in one column.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
A tile map of trend grids showing an aggregated view of all signals over time, in their spatial setting.
<div>The date is <span class="displayToday"></span>.</div>
<div class="spcTrendGridMeta"></div>
<div class="spcTrendGrid sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcTrendGrid container geo" alt="An SPC chart" ></div>
</div>
</figure>
<p>Aligning signals vertically requires a lot of space and, therefore, leaves a lot of unused space. Another approach, rather than a grid, is to have two channels (positive and negative). We still bin the time points (our columns), but now we use the height of the channel to show the most 'severe' signal (the one furthest away from the mean), and use opacity to show when multiple signal types exist in a single column. Currently, each channel occupies half of a grid square, but we can reduce that - something that will become useful later on when we show multiple visualisations in the same grid square.</p>
<figure>
<label for="mn-exports-imports" class="margin-toggle"></label><input type="checkbox" id="mn-exports-imports" class="margin-toggle">
<span class="marginnote">
A tile map of trend channels showing an aggregated view of all signals over time, in their spatial setting.
<div>The date is <span class="displayToday"></span>.</div>
<div class="spcTrendChannelMeta"></div>
<div class="spcTrendChannel sideContainer" alt="An SPC chart"></div>
</span>
<div class="containerWrapper" >
<div class="geoSpcTrendChannel container geo" alt="An SPC chart" ></div>
</div>
</figure>
<p><hr/></p>
<p>This concludes our look at design ideas for <a href="geospc.html">Representing Signals Geographically</a>.</p>
<p>On the next page we will consider design options for <a href="processes.html">Summarising Processes Geographically</a>.</p>
<p><hr/></p>
<script>
var dataFile = "data/derived_data_2016.csv";
var smwgFile = "data/west-mids-smwg.csv";
var properties = {};
var data;
var tooltip;
var mainProperties = {"autoDetectProcesses" : false};
var mapList = ["geoSpcColourOnly", "geoSpcIcons", "geoSpcGlyphs"];
var minDate = d3v45.timeParse("%m-%Y")("08-2011");
var month = 07;//11;
var year = 2014;//2012;
var today = d3v45.timeParse("%m-%Y")(month + "-" + year);
var autoDetectCap = today;
var mapData;
var selected = "";
moveTodayBackward = function() {
if (today > minDate) {
if (month > 1) {
month--;
} else {
month = 12;
year--;
}
recalculateSPC();
}
}
moveTodayForward = function() {
if (month < 12) {
month++;
} else {
month = 1;
year++;
}
recalculateSPC();
}
recalculateSPC = function() {
d3v45.selectAll(".geoSpcColourOnly").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").html("");
});
d3v45.selectAll(".geoSpcIcons").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").html("");
});
d3v45.selectAll(".geoSpcGlyphs").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").attr("transform","").html("");
});
d3v45.selectAll(".geoSpcGlyphsAngleAsMean").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").attr("transform","").html("");
});
d3v45.selectAll(".geoSpcGlyphsAngleAsMeanWidthAsCount").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").attr("transform","").html("");
});
d3v45.selectAll(".geoSpcTrendGrid").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").html("");
});
d3v45.selectAll(".geoSpcTrendChannel").each( function(d,i) {
d3v45.select(this).selectAll("g").select("g").html("");
});
d3v45.select(".loading").classed("hidden", false);
today = d3v45.timeParse("%m-%Y")(month + "-" + year);
d3v45.selectAll(".displayToday").html(displayToday());
initSPC();
}
displayToday = function() {
let s = "th";
if (d3v45.timeFormat("%_d")(today) == 1) {
s = "st";
} else if (d3v45.timeFormat("%_d")(today) == 2) {
s = "nd";
} if (d3v45.timeFormat("%_d")(today) == 3) {
s = "rd";
}
return d3v45.timeFormat("%_d" + s + " %b %Y")(today);
}
displayMeta = function(container, n) {
d3v45.select("." + container).html(n.Neighbourh + ", " + n.NPU + "<br />Population: " + n.pop2011);
}
getMapListWithoutMe = function(me) {
var tmpMapList = [];
for (let i of mapList) {
if (!(me == i)) {
tmpMapList.push(i);
}
}
return tmpMapList;
}
loadSPC = function (container) {
return function(d) {
selected = d;
for (let row of data) {
if (row.key == d) {
displayChart(row.values, "." + container, properties[d]);
for (let n of mapData) {
if (n.Neigh_code == row.key) {
displayMeta(container + "Meta", n);
}
}
break;
}
}
}
}
window.onload = function() {
tooltip = spcmap.initalizeToolip('body');
initSMWG();
d3v45.selectAll(".displayToday").html(displayToday());
}
initSMWG = function() {
d3v45.csv(smwgFile, function(error, data) {
if (error)
throw error;
mapData = data;
spcmap.drawSMWG(data, "geoSpcColourOnly", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcColourOnly"),
"callback" : loadSPC("spcColourOnly"),
"colourScale" : function(d) { return "#EEE";},
"offsetX" : 1,
"offsetY" : 0
});
spcmap.drawSMWG(data, "geoSpcIcons", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcIcons"),
"callback" : loadSPC("spcIcons"),
"colourScale" : function(d) { return "#EEE";},
"offsetX" : 1,
"offsetY" : 0
});
spcmap.drawSMWG(data, "geoSpcGlyphs", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcGlyphs"),
"callback" : loadSPC("spcGlyphs"),
"colourScale" : function(d) { return "rgba(255,255,255,0)";},
"offsetX" : 1,
"offsetY" : 0
});
spcmap.drawSMWG(data, "geoSpcGlyphsAngleAsMean", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcGlyphsAngleAsMean"),
"callback" : loadSPC("spcGlyphsAngleAsMean"),
"colourScale" : function(d) { return "rgba(255,255,255,0)";},
"offsetX" : 1,
"offsetY" : 0
});
spcmap.drawSMWG(data, "geoSpcGlyphsAngleAsMeanWidthAsCount", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcGlyphsAngleAsMeanWidthAsCount"),
"callback" : loadSPC("spcGlyphsAngleAsMeanWidthAsCount"),
"colourScale" : function(d) { return "rgba(255,255,255,0)";},
"offsetX" : 1,
"offsetY" : 0
});
spcmap.drawSMWG(data, "geoSpcTrendGrid", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcTrendGrid"),
"callback" : loadSPC("spcTrendGrid"),
"colourScale" : function(d) { return "#FFFFF8";},
"offsetX" : 1,
"offsetY" : 0
});
spcmap.drawSMWG(data, "geoSpcTrendChannel", {
"tooltip" : tooltip,
"linkedViews" : getMapListWithoutMe("geoSpcTrendChannel"),
"callback" : loadSPC("spcTrendChannel"),
"colourScale" : function(d) { return "#EEE";},
"offsetX" : 1,
"offsetY" : 0
});
initSPC();
});
}
initSPC = function() {
console.log("init");
d3v45.csv(dataFile, function(d) {
d.Count = +d.Count;
return d;
}, function(error, theData) {
if (error) throw error;
data = d3v45.nest()
.key(function(d) { return d.neighbourhood; })
.key(function(d) { return d.Month; })
.rollup(function(v) {
return d3v45.sum(v, function(d) {
return d.Count;
})
})
.entries(theData);
data.forEach(function(d) {
d.values.forEach( function (d) {
d.Date = spc.parseTime("%Y-%m")(d.key);
d.Count = +d.value;
});
d.values.sort(function(a,b) {return a.Date-b.Date;});
let i = 0;
while(d.values[i].Date <= today) {
i++;
}
d.values.splice(i, d.values.length);
spc.getSignals(d.values, properties[d.key] = {"autoDetectProcess" : true, "autoDetectUntil" : autoDetectCap});
spcmap.addSignalsAsColourOnly("geoSpcColourOnly", d.key, properties[d.key], today);
spcmap.addSignalsAsIcons("geoSpcIcons", d.key, properties[d.key], today);
spcmap.addSignalsAsGlyphs("geoSpcGlyphs", d.key, properties[d.key], today, "#CCC");
spcmap.addSignalsAsGlyphsAngleAsMean("geoSpcGlyphsAngleAsMean", d.key, properties[d.key], today, d.values, false, "#CCC");
spcmap.addSignalsAsGlyphsAngleAsMean("geoSpcGlyphsAngleAsMeanWidthAsCount", d.key, properties[d.key], today, d.values, true, "#CCC");
spcmap.addSignalsAsTemporalGrid("geoSpcTrendGrid", d.key, properties[d.key], d.values);
spcmap.addSignalsAsTrendChannel("geoSpcTrendChannel", d.key, properties[d.key], d.values, 0.5);
});
if (selected != "") {
loadSPC(selected);
}
console.log("finished");
d3v45.select(".loading").classed("hidden", true);
});
}
</script>
</body>
</html>