Skip to content

Instantly share code, notes, and snippets.

@zeffii
Last active June 13, 2016 12:24
Glucose - nested v5 - comments
/*
MIT License 2016 - Dealga McArdle.
=================================
For now this is moderately light usage of d3.js - maybe to the chagrin of more weathered
d3.js masters - simply to illustrate a problem i'm facing.
typical json to parse:
....
"YYYY/MM/DD": {
"sleeptimes": "00:00->07:00,15:20->18:30,23:00->24:00",
"comments": "AMC visit, Cystoscopy - all clear",
"glucose": [
{"time": "06:35", "value": 6.94},
{"time": "15:18", "value": 14.93},
{"time": "20:28", "value": 11.77},
{"time": "22:13", "value": 12.71}
]
},
....
- could color grade using 0-5 5-10 10-15 15-20 20-25 25-up
intentionally left blank.
*/
function get_ratio_from_time(time_str){
// this function converts a time_str into how far into the day it is
// f.ex 12:00 => 0.5 06:00 => 0.25
var time_parts = time_str.split(':');
var a = +time_parts[0];
var b = +time_parts[1];
return (1/1440*((a*60) + b))
}
function get_color(tval){
if (tval < 5.0){return {bg:"#18dff5", tx: "#111"}}
else if (tval >= 5.0 && tval < 10.0){return {bg:"#27f518", tx: "#111"}}
else if (tval >= 10.0 && tval < 15.0){return {bg:"#c8f97f", tx: "#111"}}
else if (tval >= 15.0 && tval < 20.0){return {bg:"#ffb76b", tx: "#111"}}
else if (tval >= 20.0){return {bg:"#fe70bc", tx: "#ffffff"}}
}
var svg = d3.select("svg")
var format_day = d3.time.format("%Y/%m/%d");
var format_hours = d3.time.format("%H:%M");
var formatTime = d3.time.format("%m / %d");
d3.json("times.json", function(error, times) {
if (error) throw error;
times = json_preprocessor(times);
draw_graph(times);
});
function times_preprocessor(t){
if (!t){return []}
var ts = t.split(',');
var emb = [];
for (var k of ts){
var abl = k.split('->');
if (abl.length === 2){ emb.push(abl); }
}
return emb;
}
function json_preprocessor(p){
var new_object_array = [];
for (var key in p) {
if (p.hasOwnProperty(key)) {
var day_datum = format_day.parse(key);
var time_object = p[key];
var processed_times = times_preprocessor(time_object.sleeptimes);
new_object_array.push({
day: day_datum,
times: processed_times,
comments: time_object.comments,
glucose: time_object.glucose
});
}
}
return new_object_array;
}
function draw_graph(times){
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
svg
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var main_group = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var tracks = main_group.append('g').classed('tracks', true)
var yindex = 0;
var begin_time, end_time;
var tab_height = 12;
var bar_height = 15;
var tab_ear = 4;
var vertical_skip = 17;
var time_offset_down = 6;
for (var item of times){
var mg = tracks.append('g');
for (var time_slot of item.times){
begin_time = get_ratio_from_time(time_slot[0]);
end_time = get_ratio_from_time(time_slot[1]);
var rec = mg.append('rect');
rec.attr("width", (end_time - begin_time) * width)
.attr("height", bar_height)
.style({fill: "#badcfc"})
.attr("transform", function(d){
return "translate(" + [
begin_time * width,
yindex * vertical_skip
] + ")"
})
}
var gg = tracks.append('g');
for (var reading of item.glucose){
var gtime = get_ratio_from_time(reading.time);
var gval = reading.value;
var ggroup = gg.append('g');
ggroup.attr({
transform: "translate(" + [0, (yindex * vertical_skip + 8)] + ")"})
var cl = ggroup.append('rect');
cl.attr({transform: "translate(" + [(gtime * width) + tab_ear , -6] +")"})
.attr({'height': tab_height})
.style({fill: get_color(gval).bg})
var cl2 = ggroup.append('path');
cl2.attr({transform: "translate(" + [(gtime * width) + tab_ear , -6] +")"})
.attr({'d': 'M' + [0,0,-tab_ear,tab_height/2,0,tab_height] + 'z'})
.style({fill: get_color(gval).bg})
var cltext = ggroup.append('text');
cltext.text(gval)
.attr({transform: "translate(" + [(gtime * width) + tab_ear , 4] +")"})
.attr({
'text-anchor': "start",
"font-size": 11,
"font-family": "sans-serif"
})
cltext.style({'fill': get_color(gval).tx })
var textwidth = cltext.node().getComputedTextLength();
cl.attr({'width': textwidth})
}
// draw comments
if (item.comments.length > 0){
var comment_group = mg.append('g');
comment_group.attr({
transform: "translate(" + [width + 20, yindex * vertical_skip] + ")"
})
var newrec = comment_group.append('rect')
newrec.attr('width', 20).attr('height', 13)
newrec.style({fill: "#fce7ba"})
}
yindex += 1;
mg.append('text')
.text(formatTime(item.day))
.attr("transform", "translate(-21," + (yindex * vertical_skip - 7) + ")")
.attr({'text-anchor': "middle", "font-size": 10, "font-family": "sans-serif"})
}
var indicat = main_group.append('g').classed('indications', true);
var ditimes = "00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24".split(" ");
var circle_push_vertical = 1.7799417856; // <---- use to push hourly circles up / down
var time_index = 0;
for (var tick of ditimes){
tick = tick + ":00";
var tgl = indicat.append('g');
var tl = tgl.append('line');
var xpostime = Math.floor(get_ratio_from_time(tick) * width);
tl.attr('x1', xpostime)
.attr('x2', xpostime)
.attr('y1', 0)
.attr('y2', height)
.style({"stroke-width": 1, stroke: "#cfdbe7"})
if (time_index % 3 === 0){
tl.style({"stroke-width": 1, stroke: "#aabfd4"})
var tcl = tgl.append('circle');
tcl.attr('cx', Math.floor(get_ratio_from_time(tick) * width))
.attr('cy', height/circle_push_vertical)
.attr('r', 16)
.style({fill: "#e0eeff"})
var txl = tgl.append('text');
txl.attr({
'text-anchor': "middle",
"font-size": 17,
"font-family": "sans-serif"
})
.attr(
'transform',
'translate(' + [
Math.floor(get_ratio_from_time(tick) * width),
(height/circle_push_vertical)+time_offset_down ] +
')')
.style({'fill': "#7c7c7c"})
.text(tick.slice(0,2))
}
time_index += 1;
}
}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://d3js.org/d3-time.v0.2.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css" />
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg { width:100%; height: 100% }
</style>
</head>
<body>
<svg></svg>
<script src="dillitant.js"></script>
</body>
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font: 10px sans-serif;
}
{
"2016/06/01": {
"comments": "",
"glucose": [
{
"time": "08:06",
"value": 7.94
},
{
"time": "11:47",
"value": 18.32
},
{
"time": "16:45",
"value": 18.87
},
{
"time": "22:12",
"value": 13.04
}
],
"times": ""
},
"2016/06/02": {
"comments": "",
"glucose": [
{
"time": "08:04",
"value": 6.99
},
{
"time": "13:15",
"value": 11.27
},
{
"time": "18:11",
"value": 21.48
},
{
"time": "22:03",
"value": 15.21
}
],
"times": ""
},
"2016/06/03": {
"comments": "",
"glucose": [
{
"time": "07:44",
"value": 8.88
},
{
"time": "11:53",
"value": 17.71
},
{
"time": "17:37",
"value": 22.54
},
{
"time": "22:12",
"value": 19.65
}
],
"times": ""
},
"2016/06/04": {
"comments": "",
"glucose": [
{
"time": "06:57",
"value": 10.77
},
{
"time": "12:06",
"value": 13.27
},
{
"time": "16:44",
"value": 17.26
}
],
"times": ""
},
"2016/06/05": {
"comments": "",
"glucose": [
{
"time": "03:08",
"value": 18.43
},
{
"time": "08:22",
"value": 16.15
},
{
"time": "13:07",
"value": 13.21
},
{
"time": "17:42",
"value": 16.26
},
{
"time": "22:02",
"value": 17.82
}
],
"times": ""
},
"2016/06/06": {
"comments": "",
"glucose": [
{
"time": "08:07",
"value": 8.16
},
{
"time": "12:12",
"value": 18.37
},
{
"time": "18:32",
"value": 19.48
},
{
"time": "22:30",
"value": 17.93
}
],
"times": ""
},
"2016/06/07": {
"comments": "",
"glucose": [
{
"time": "07:07",
"value": 7.05
},
{
"time": "12:15",
"value": 8.44
},
{
"time": "17:04",
"value": 17.54
},
{
"time": "22:41",
"value": 10.66
}
],
"times": ""
},
"2016/06/08": {
"comments": "",
"glucose": [
{
"time": "08:07",
"value": 9.6
},
{
"time": "12:18",
"value": 17.71
},
{
"time": "16:58",
"value": 17.04
},
{
"time": "21:26",
"value": 18.76
}
],
"times": ""
},
"2016/06/09": {
"comments": "",
"glucose": [
{
"time": "07:10",
"value": 9.44
},
{
"time": "12:04",
"value": 21.09
},
{
"time": "17:04",
"value": 16.6
},
{
"time": "22:08",
"value": 15.71
}
],
"times": ""
},
"2016/06/10": {
"comments": "",
"glucose": [
{
"time": "07:04",
"value": 11.49
},
{
"time": "12:18",
"value": 18.21
},
{
"time": "18:51",
"value": 19.43
},
{
"time": "22:33",
"value": 21.76
}
],
"times": ""
},
"2016/06/11": {
"comments": "",
"glucose": [
{
"time": "06:34",
"value": 7.27
},
{
"time": "13:23",
"value": 23.92
},
{
"time": "18:21",
"value": 26.53
},
{
"time": "22:27",
"value": 26.64
}
],
"times": ""
},
"2016/06/12": {
"comments": "",
"glucose": [
{
"time": "06:56",
"value": 11.43
},
{
"time": "12:21",
"value": 17.37
},
{
"time": "17:26",
"value": 25.53
},
{
"time": "22:08",
"value": 22.87
}
],
"times": ""
},
"2016/06/13": {
"comments": "",
"glucose": [
{
"time": "06:32",
"value": 14.49
},
{
"time": "07:45",
"value": 13.1
},
{
"time": "13:04",
"value": 23.59
}
],
"times": ""
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment