Built with blockbuilder.org
Last active
September 21, 2016 20:03
-
-
Save ssaleh2/d70a6d6480ecdcbf9f6afd1840579c51 to your computer and use it in GitHub Desktop.
multi-line HR alarm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Time | Heart_Rate | Alarm_LOW | Alarm_HIGH | Alarm_Seg | ||
---|---|---|---|---|---|---|
17 | 2234 | 69 | 60 | 110 | ||
18 | 2236 | 70 | 60 | 110 | ||
0 | 2200 | 74 | 60 | 110 | ||
1 | 2202 | 74 | 60 | 110 | ||
0 | 2200 | 74 | 60 | 110 | ||
1 | 2202 | 74 | 60 | 110 | ||
2 | 2204 | 73 | 60 | 110 | ||
3 | 2206 | 72 | 60 | 110 | ||
13 | 2226 | 69 | 60 | 110 | ||
14 | 2228 | 69 | 60 | 110 | ||
6 | 2212 | 72 | 60 | 110 | ||
7 | 2214 | 72 | 60 | 110 | ||
8 | 2216 | 72 | 60 | 110 | ||
9 | 2218 | 81 | 60 | 110 | ||
10 | 2220 | 80 | 60 | 110 | ||
11 | 2222 | 79 | 60 | 110 | ||
12 | 2224 | 74 | 60 | 110 | ||
13 | 2226 | 69 | 60 | 110 | ||
14 | 2228 | 69 | 60 | 110 | ||
15 | 2230 | 69 | 60 | 110 | ||
16 | 2232 | 69 | 60 | 110 | ||
17 | 2234 | 69 | 60 | 110 | ||
18 | 2236 | 70 | 60 | 110 | ||
0 | 2200 | 74 | 60 | 110 | ||
1 | 2202 | 74 | 60 | 110 | ||
2 | 2204 | 73 | 60 | 110 | ||
11 | 2222 | 79 | 60 | 110 | ||
12 | 2224 | 74 | 60 | 110 | ||
13 | 2226 | 69 | 60 | 110 | ||
14 | 2228 | 69 | 60 | 110 | ||
15 | 2230 | 69 | 60 | 110 | ||
16 | 2232 | 69 | 60 | 110 | ||
2 | 2204 | 73 | 60 | 110 | ||
3 | 2206 | 72 | 60 | 110 | ||
4 | 2208 | 72 | 60 | 110 | ||
10 | 2220 | 80 | 60 | 110 | ||
11 | 2222 | 79 | 60 | 110 | ||
12 | 2224 | 74 | 60 | 110 | ||
13 | 2226 | 69 | 60 | 110 | ||
14 | 2228 | 69 | 60 | 110 | ||
15 | 2230 | 69 | 60 | 110 | ||
16 | 2232 | 69 | 60 | 110 | ||
17 | 2234 | 69 | 60 | 110 | ||
18 | 2236 | 70 | 60 | 110 | ||
19 | 2238 | 70 | 60 | 110 | ||
20 | 2240 | 70 | 60 | 110 | ||
21 | 2242 | 70 | 60 | 110 | ||
22 | 2244 | 71 | 60 | 110 | ||
23 | 2246 | 72 | 60 | 110 | ||
24 | 2248 | 73 | 60 | 110 | ||
25 | 2250 | 73 | 60 | 110 | ||
26 | 2252 | 74 | 60 | 110 | ||
27 | 2254 | 74 | 60 | 110 | ||
29 | 2258 | 75 | 60 | 110 | ||
27 | 2254 | 74 | 60 | 110 | ||
28 | 2256 | 75 | 60 | 110 | ||
29 | 2258 | 75 | 60 | 110 | ||
28 | 2256 | 75 | 60 | 110 | ||
29 | 2258 | 75 | 60 | 110 | ||
27 | 2254 | 74 | 60 | 110 | ||
28 | 2256 | 75 | 60 | 110 | ||
29 | 2258 | 75 | 60 | 110 | ||
30 | 2260 | 74 | 60 | 110 | ||
31 | 2262 | 74 | 50 | 100 | ||
32 | 2264 | 74 | 50 | 100 | ||
33 | 2266 | 65 | 50 | 100 | ||
34 | 2268 | 53 | 50 | 100 | ||
35 | 2270 | 50 | 50 | 100 | 50 | |
36 | 2272 | 48 | 50 | 100 | 48 | |
37 | 2274 | 42 | 50 | 100 | 42 | |
38 | 2276 | 42 | 50 | 100 | 42 | |
39 | 2278 | 45 | 50 | 100 | 45 | |
40 | 2280 | 45 | 50 | 100 | 45 | |
41 | 2282 | 50 | 50 | 100 | 50 | |
42 | 2284 | 60 | 50 | 100 | ||
43 | 2286 | 75 | 50 | 100 | ||
44 | 2288 | 75 | 50 | 100 | ||
45 | 2290 | 75 | 50 | 100 | ||
46 | 2292 | 75 | 50 | 100 | ||
47 | 2294 | 75 | 50 | 100 | ||
48 | 2296 | 75 | 50 | 100 | ||
49 | 2298 | 75 | 50 | 100 | ||
50 | 2300 | 75 | 50 | 100 | ||
51 | 2302 | 75 | 50 | 100 | ||
52 | 2304 | 75 | 50 | 100 | ||
53 | 2306 | 75 | 50 | 100 | ||
54 | 2308 | 75 | 50 | 100 | ||
55 | 2310 | 75 | 50 | 100 | ||
56 | 2312 | 75 | 50 | 100 | ||
57 | 2314 | 75 | 50 | 100 | ||
58 | 2316 | 76 | 50 | 100 | ||
59 | 2318 | 76 | 50 | 100 | ||
60 | 2320 | 76 | 50 | 100 | ||
61 | 2322 | 75 | 50 | 100 | ||
62 | 2324 | 67 | 50 | 100 | ||
63 | 2326 | 67 | 50 | 100 | ||
64 | 2328 | 67 | 50 | 100 | ||
65 | 2330 | 61 | 50 | 100 | ||
66 | 2332 | 50 | 50 | 100 | 50 | |
67 | 2334 | 47 | 50 | 100 | 47 | |
68 | 2336 | 47 | 50 | 100 | 47 | |
69 | 2338 | 50 | 50 | 100 | 50 | |
70 | 2340 | 57 | 50 | 100 | ||
71 | 2342 | 87 | 50 | 100 | ||
72 | 2344 | 87 | 50 | 100 | ||
73 | 2346 | 90 | 50 | 100 | ||
74 | 2348 | 90 | 50 | 100 | ||
75 | 2350 | 100 | 50 | 100 | ||
76 | 2352 | 84 | 50 | 100 | ||
77 | 2354 | 73 | 50 | 100 | ||
78 | 2356 | 73 | 50 | 100 | ||
79 | 2358 | 81 | 50 | 100 | ||
80 | 2360 | 78 | 50 | 100 | ||
81 | 2362 | 77 | 50 | 100 | ||
82 | 2364 | 70 | 50 | 100 | ||
83 | 2366 | 69 | 50 | 100 | ||
84 | 2368 | 70 | 50 | 100 | ||
85 | 2370 | 71 | 50 | 100 | ||
86 | 2372 | 74 | 50 | 100 | ||
87 | 2374 | 77 | 50 | 100 | ||
88 | 2376 | 74 | 50 | 100 | ||
89 | 2378 | 80 | 50 | 100 | ||
90 | 2380 | 79 | 50 | 100 | ||
91 | 2382 | 78 | 50 | 100 | ||
92 | 2384 | 78 | 50 | 100 | ||
93 | 2386 | 88 | 50 | 100 | ||
94 | 2388 | 83 | 50 | 100 | ||
95 | 2390 | 77 | 50 | 100 | ||
96 | 2392 | 87 | 50 | 100 | ||
97 | 2394 | 86 | 50 | 100 | ||
98 | 2396 | 86 | 50 | 100 | ||
99 | 2398 | 75 | 50 | 100 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
} | |
.graph .axis { | |
stroke-width: 1; | |
} | |
.graph .axis .tick line { | |
stroke: black; | |
} | |
.graph .axis .tick text { | |
fill: black; | |
font-size: 0.7em; | |
} | |
.graph .axis .domain { | |
fill: none; | |
stroke: black; | |
} | |
.graph .group { | |
fill: none; | |
stroke: black; | |
stroke-width: 2.5; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="graph"></div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var limit = 60 * 1, | |
duration = 1000, | |
now = new Date(Date.now() - duration) | |
var width = 800, | |
height = 400 | |
var x = d3.time.scale() | |
.domain([now - (limit - 2), now - duration]) | |
.range([0, width]) | |
var y = d3.scale.linear() | |
.domain([20, 180]) | |
.range([height-7, 0+7]) | |
var maxIndex = 60; | |
var minIndex = 0; | |
var fullData; | |
var subset; | |
var pitch = 764.81; | |
var index_change_thresh; | |
// var formatDate = d3.time.parse("%Y-%m-%d %H:%M:%S"); | |
var circle = null; | |
var circleTransition = null; | |
var latestBeat = null; | |
var insideBeat = false; | |
var SECONDS_SAMPLE = 5; | |
var BEAT_TIME = 400; | |
var TICK_FREQUENCY = SECONDS_SAMPLE * 1000 / BEAT_TIME; | |
var BEAT_VALUES = [0, 0, 3, -4, 10, -7, 3, 0, 0]; | |
var CIRCLE_FULL_RADIUS = 40; | |
var MAX_LATENCY = 5000; | |
var colorScale = d3.scale.linear() | |
.domain([BEAT_TIME, (MAX_LATENCY - BEAT_TIME) / 2, MAX_LATENCY]) | |
.range(["#6D9521", "#D77900", "#CD3333"]); | |
var radiusScale = d3.scale.linear() | |
.range([5, CIRCLE_FULL_RADIUS]) | |
.domain([MAX_LATENCY, BEAT_TIME]); | |
d3.csv("data.csv", function(error, data) { | |
if (error) throw error; | |
fullData = data; | |
data.forEach(function(d) { | |
d.index = +d.index; | |
d.Time = +d.Time - 2200; | |
d.Heart_Rate = +d.Heart_Rate; | |
d.Alarm_LOW = +d.Alarm_LOW; | |
d.Alarm_HIGH = +d.Alarm_HIGH; | |
d.Alarm_Seg = +d.Alarm_Seg; | |
}); | |
subset = data.slice(minIndex, maxIndex); | |
var groups = { | |
alarm_top: { | |
value: 0, | |
color: 'grey', | |
data: subset.map(function(d){ | |
return d.Alarm_HIGH | |
}) | |
}, | |
HR: { | |
value: 0, | |
color: 'green', | |
data: subset.map(function(d){ | |
return d.Heart_Rate | |
}) | |
}, | |
alarm_bottom: { | |
value: 0, | |
color: 'grey', | |
data: subset.map(function(d){ | |
return d.Alarm_LOW | |
}) | |
}, | |
alarm_seg: { | |
value: 0, | |
color: 'red', | |
data: subset.map(function(d){ | |
return d.Alarm_Seg | |
}), | |
} | |
} | |
var svg = d3.select('.graph').append('svg') | |
.attr('class', 'chart') | |
.attr('width', width) | |
.attr('height', height + 50) | |
var line = d3.svg.line() | |
.interpolate('basis') | |
.defined(function(d) { return d; }) | |
.x(function(d, i) { | |
return x(now - (limit - 1 - i) * duration) | |
}) | |
.y(function(d) { | |
return y(d) | |
}); | |
var alarm = d3.svg.line() | |
.interpolate('step') | |
.defined(function(d) { return d; }) | |
.x(function(d, i) { | |
return x(now - (limit - 1 - i) * duration) | |
}) | |
.y(function(d) { | |
return y(d) | |
}); | |
// circle = svg.append("circle") | |
// .attr("fill", "#6D9521") | |
// .attr("cx", width - 50) | |
// .attr("cy", height / 8) | |
// .attr("r", CIRCLE_FULL_RADIUS); | |
logo_image = svg.append("svg:image") | |
.attr("xlink:href", "https://photos-2.dropbox.com/t/2/AADrvzJAKGZ_hOE5bIMmTNZbqMyDYIae80OBZySunn9huw/12/44674655/png/32x32/1/_/1/2/precisely_no_shadow.png/ELKvmSIYqCwgBygH/468DdTQyet8GP-yo8y3b7M9JiwEWLPCEdNtewgcPu3k?size=1600x1200&size_mode=3") | |
.attr("x", function(d) { return 700;}) | |
.attr("y", function(d) { return 0;}) | |
.attr("width", 85) | |
.attr("height", 85); | |
dx_image = svg.append("svg:image") | |
.attr("xlink:href", "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTGdTw9a2xeKGu4ezKtjwutax0XzkBuTa2yrtDZ-wTu4g5mgcv2") //"https://cdn0.iconfinder.com/data/icons/healthcare-and-medicine-kit/512/medical_test_stethoscope-512.png") | |
.attr("x", function(d) { return 130;}) | |
.attr("y", function(d) { return 25;}) | |
.attr("width", 55) | |
.attr("height", 55); | |
dem_image = svg.append("svg:image") | |
.attr("xlink:href", "http://www.arlington-tx.gov/cdp/wp-content/uploads/sites/11/2014/04/Demographics.png") | |
.attr("x", function(d) { return 65;}) | |
.attr("y", function(d) { return 25;}) | |
.attr("width", 55) | |
.attr("height", 55); | |
icu_image = svg.append("svg:image") | |
.attr("xlink:href", "http://fcmcng.com/wp-content/uploads/2015/03/ICU_Icon-08.png") | |
.attr("x", function(d) { return 195;}) | |
.attr("y", function(d) { return 25;}) | |
.attr("width", 55) | |
.attr("height", 55); | |
var med_image = null, | |
plus = null; | |
var gradient = svg.append("defs") | |
.append("linearGradient") | |
.attr("id", "gradient") | |
.attr("x1", "0%") | |
.attr("y1", "0%") | |
.attr("x2", "100%") | |
.attr("y2", "0%") | |
.attr("spreadMethod", "pad"); | |
gradient.append("stop") | |
.attr("offset", "0%") | |
.attr("stop-color", "#D14424") | |
.attr("stop-opacity", 0.3); | |
gradient.append("stop") | |
.attr("offset", "100%") | |
.attr("stop-color", "#D14424") | |
.attr("stop-opacity", 0.1); | |
svg.append("rect") | |
.attr("width", width) | |
.attr("height", height) | |
.style("fill", "url(#gradient)"); | |
var Yaxis = svg.append('g') | |
.attr('class', 'y axis') | |
.attr("transform", "translate (" + 35 + ", 0)") | |
.call(y.axis = d3.svg.axis().scale(y).orient("left")) | |
var Xaxis = svg.append('g') | |
.attr('class', 'x axis') | |
.attr('transform', 'translate(0,' + height + ')') | |
.call(x.axis = d3.svg.axis().scale(x).orient('bottom')) | |
var paths = svg.append('g') | |
groups['HR'].path = paths.append('path') | |
.data([groups['HR'].data]) | |
.attr('class', 'HR' + ' group') | |
.style('stroke', groups['HR'].color) | |
groups['alarm_top'].path = paths.append('path') | |
.data([groups['alarm_top'].data]) | |
.attr('class', 'alarm_top' + ' group') | |
.style('stroke', groups['alarm_top'].color) | |
groups['alarm_bottom'].path = paths.append('path') | |
.data([groups['alarm_bottom'].data]) | |
.attr('class', 'alarm_bottom' + ' group') | |
.style('stroke', groups['alarm_bottom'].color) | |
groups['alarm_seg'].path = paths.append('path') | |
.data([groups['alarm_seg'].data]) | |
.attr('class', 'alarm_seg' + ' group') | |
.style('stroke', groups['alarm_seg'].color) | |
//audio context | |
var ac = this.AudioContext ? new AudioContext() : new webkitAudioContext(); | |
ac.createGain(); | |
//generate oscillator | |
function osc(pitch, waveform){ | |
// var ac = new AudioContext(), | |
oscillator = ac.createOscillator(), | |
oscillator.type = waveform; | |
oscillator.frequency.value = pitch; | |
gainNode = ac.createGain(); | |
oscillator.connect(gainNode); | |
gainNode.connect(ac.destination); | |
gainNode.gain.value = .2; | |
return {osc: oscillator, gain: gainNode}; | |
}; | |
function tick() { | |
//add new values | |
now = new Date() | |
groups['HR'].data.push(fullData[maxIndex]['Heart_Rate']) | |
groups['HR'].path.attr('d', line) | |
// when lower alarm limit changes | |
if (fullData[maxIndex]['Alarm_LOW'] != groups['alarm_bottom'].data[groups['alarm_bottom'].data.length-1]){ | |
index_change_thresh = maxIndex; | |
med_image = svg.append('g') | |
.append("svg:image") | |
.attr("xlink:href", "https://cdn3.iconfinder.com/data/icons/medical-8/512/medication-512.png") | |
.attr("class", "add_med") | |
.attr("x", function(d) { return index_change_thresh*800/60 -85;}) | |
.attr("y", function(d) { return 100;}) | |
.attr("width", 55) | |
.attr("height", 55); | |
plus = svg.append('g') | |
.append("svg:image") | |
.attr("xlink:href", "http://www.freeiconspng.com/uploads/plus-icon-black-2.png") | |
.attr("class", "add_med") | |
.attr("x", function(d) { return index_change_thresh*800/60 -110;}) | |
.attr("y", function(d) { return 108;}) | |
.attr("width", 45) | |
.attr("height", 45); | |
}; | |
//Move medication along axis | |
if (fullData[maxIndex]['Alarm_LOW'] == groups['alarm_bottom'].data[groups['alarm_bottom'].data.length-1] && plus != null){ | |
index_change_thresh -= 1.15; | |
plus.attr("x", function(d) { return index_change_thresh*800/60 - 110;}) | |
med_image.attr("x", function(d) { return index_change_thresh*800/60 -85;}) | |
}; | |
groups['alarm_bottom'].data.push(fullData[maxIndex]['Alarm_LOW']) | |
groups['alarm_bottom'].path.attr('d', alarm) | |
groups['alarm_top'].data.push(fullData[maxIndex]['Alarm_HIGH']) | |
groups['alarm_top'].path.attr('d', alarm) | |
groups['alarm_seg'].data.push(fullData[maxIndex]['Alarm_Seg']) | |
groups['alarm_seg'].path.attr('d', line) | |
// console.log(dem_image) | |
// index_change_thresh -= 1.15; | |
// d3.select("add_med").attr('transform', 'translate(' + index_change_thresh*800/60 - 110 +')') | |
// .transition() | |
// .attr(attr("x", function(d) { return index_change_thresh*800/60 - 110;})) | |
// .duration(duration) | |
// .ease('linear') | |
// .attr('transform', 'translate(' + x(now - (limit - 1) * duration) + ')') | |
// .each('end', tick) | |
maxIndex += 1; | |
// Shift domain | |
x.domain([now - (limit - 2) * duration, now - duration]) | |
// Slide x-axis left | |
Xaxis.transition() | |
.duration(duration) | |
.ease('linear') | |
.call(x.axis) | |
// Slide paths left | |
paths.attr('transform', null) | |
.transition() | |
.duration(duration) | |
.ease('linear') | |
.attr('transform', 'translate(' + x(now - (limit - 1) * duration) + ')') | |
.each('end', tick) | |
//play alarm sound | |
if (fullData[maxIndex]['Alarm_Seg']!=0){ | |
var o = osc(pitch, 'sine'); | |
o.osc.start(ac.currentTime + 3.5); | |
o.osc.stop(ac.currentTime + 3.75); | |
} | |
// Remove oldest data point from each group | |
for (var name in groups) { | |
var group = groups[name] | |
group.data.shift() | |
} | |
} | |
tick() | |
}) | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment