Skip to content

Instantly share code, notes, and snippets.

@Mbrownshoes
Last active June 17, 2018 22:46
Show Gist options
  • Select an option

  • Save Mbrownshoes/7e5f8625242bd7a92965c702ed9065d4 to your computer and use it in GitHub Desktop.

Select an option

Save Mbrownshoes/7e5f8625242bd7a92965c702ed9065d4 to your computer and use it in GitHub Desktop.
// var QueryString = function() {
// // This function is anonymous, is executed immediately and
// // the return value is assigned to QueryString!
// var query_string = {};
// var query = window.location.search.substring(1);
// var vars = query.split("&");
// for (var i = 0; i < vars.length; i++) {
// var pair = vars[i].split("=");
// // If first entry with this name
// if (typeof query_string[pair[0]] === "undefined") {
// query_string[pair[0]] = decodeURIComponent(pair[1]);
// // If second entry with this name
// } else if (typeof query_string[pair[0]] === "string") {
// var arr = [query_string[pair[0]], decodeURIComponent(pair[1])];
// query_string[pair[0]] = arr;
// // If third or later entry with this name
// } else {
// query_string[pair[0]].push(decodeURIComponent(pair[1]));
// }
// }
// return query_string.id;
// }();
var aqhi, test, x, y, x2, y2, height, focus, context, line, line2, labels, bisectDate, focus1, parseTime, formatTime, ylab, met, thesLine
var list_of_aq_measures = []
// d3.csv('labels.csv', function(err, data) {
// labels = data
// })
var named = [];
// var formatTime = d3.timeFormat("%b %e");
var d = new Date();
var startT = new Date();
startT.setMonth(startT.getMonth() - 1)
// console.log(startT)
// d.toISOString().split('.')[0]+"Z"
console.log(d.toISOString().split('.')[0]+"Z")
d3.json('http://erddap.aoos.org/erddap/tabledap/org_hakai_quadra.json?time%2Cstation%2CpCO2%2Comega_aragonite%2Csea_water_temperature%2Cdissolved_carbon_dioxide_co2%2Csea_water_practical_salinity%2Csea_water_ph_reported_on_total_scale%2Csea_water_alkalinity_expressed_as_mole_equivalent%2Cdepth&time%3E='+startT.toISOString().split('.')[0]+"Z"+'&time%3C='+ d.toISOString().split('.')[0]+"Z", function(err, data) {
// console.log(data.table.rows[1])
test = data.table
colNames = data.table.columnNames
colUnits = data.table.columnUnits
colUnits.splice(0,2) //remove elementes we don't want to plot
data = data.table.rows
// console.log(colNames)
// data.pop(1)
// initGas = 'TEMP_MEAN'
// if (QueryString.includes('AQHI')){
// initGas = ''
// }
//build list of measures
var IsoParse = d3.utcParse("%Y-%m-%dT%H:%M:%S%Z");
parseTime = d3.timeParse("%Y-%m-%d %H:%M");
formatTime = d3.timeFormat("%Y-%m-%d %H:%M");
formatMonth = d3.timeFormat("%b %d %H:%M");
// if (!(initGas in data[1]))
// initGas = Object.keys(data[0])[1]
data.forEach(function(d, i) {
//name keys using colNames
colNames.forEach(function(dd,ii){
d[colNames[ii]] = d[ii]
})
d.DATE_PST = IsoParse(d[0])
d.splice(0,12)
})
data.sort((a, b) => a.DATE_PST - b.DATE_PST);
console.log(data[1])
bisectDate = d3.bisector(function(d) {
return d.DATE_PST;
}).left;
test = data
meas = [];
var orderPoll = ["PM25", "PM25_24HR", "PM10", "PM10_24HR", "O3", "O3_8HR", "NO2", "NO2_24"]
var orderMet = ["WSPD_SCLR", "WSPD_VECT", "TEMP_MEAN", "WDIR_VECT"]
var exclude = ['time', 'latitude', 'longitude', 'station', 'DATE_LOCAL']
met = ['TEMP_MEAN', 'WDIR_UVEC', 'WDIR_VECT', 'WSPD_SCLR', 'WSPD_VECT']
thres = {
'PM25_24HR': 25,
"PM10_24HR": 50,
'O3_8hr': 63,
'NO2': 100,
'SO2': 70,
'depth': 100
}
console.log(data[0])
// debugger
$.each(data[0], function(key, value) {
console.log(key)
// if (!(exclude.includes(key))) {
// ind = _(labels).filter(function(d) {
// return d['Data Source'] === key;
// });
// if (ind.length > 0) {
// if (ind[0]['Data Source'] == 'TEMP_MEAN') {
// ind[0]['Units'] = '\xB0C'
// } else if (ind[0]['Data Source'] == 'PM25') {
// ind[0]['Units'] = '\u03BC g/m3'
// } else if (ind[0]['Data Source'] == 'WDIR_UVEC' || ind[0]['Data Source'] == 'WDIR_VECT') {
// ind[0]['Units'] = '\xB0'
// }
// console.log(ind)
// meas.push({
// source: ind[0]['Data Source'],
// short: ind[0]['Short Name'],
// unit: ind[0]['Units']
// })
// }
// list_of_aq_measures.push(key)
// }
});
list_of_aq_measures = colNames
var result = []
orderPoll.forEach(function(key) {
list_of_aq_measures.forEach(function(item) {
if (item == key) {
result.push(item)
}
})
})
orderMet.forEach(function(key) {
list_of_aq_measures.forEach(function(item) {
if (item == key) {
result.push(item)}
})
})
arr3 = result.concat(list_of_aq_measures)
list_of_aq_measures=[...new Set(arr3)]
i_unit = 2; //plot this trace first
initGas = list_of_aq_measures[i_unit]
// console.log(initGas)
colorScale = d3.scaleOrdinal(d3.schemeCategory10);
var newmeas=[]
list_of_aq_measures.forEach(function(d){
if(!(exclude.includes(d))){
newmeas.push(d)
}
})
// list_of_aq_measures = newmeas
// console.log(newmeas)
makeButtons(newmeas, data);
makeGraphs(initGas, data)
d3.select(".current-cond").html(data[0]["station"]);
d3.select(".current-date").html(formatTime(data[data.length - 1].DATE_PST));
});
function makeActive(selection) {
d3.selectAll(".active").classed("active", false).attr('style', 'border: solid 0px black !important;')
selection.classed("active", true).attr('style',
function(d) {
return 'border: solid 2px ' + '#ff7f0e' + ' !important;'
})
}
t = 0
function makeButtons(keys, data) {
var buttons = d3.select('.button').selectAll('.button')
.data(keys)
.enter()
.append("button")
.attr("class", "btn btn-default")
.attr('id', function(d,i){
// console.log(d)
return d;
})
.text(function(d, i) {
lab = d
meas.forEach(function(j) {
// lab = d
if (d == j['source']) {
lab = j['short'];
}
})
// console.log(lab)
return lab
})
.on("click", function(d,i_unit) {
console.log(i_unit)
if(d !== 'FORECAST_TONIGHT' && d !== 'FORECAST_TODAY' && d !== 'FORECAST_TOMORROW'){
t += 1
makeActive(d3.select(this));
updateGraph(d, data,i_unit)
}
// }
})
// append values to buttons
buttons.append("div")
.attr("class", 'val')
.data(keys)
.html(function(d, i) {
lab = ''
meas.forEach(function(j) {
console.log(j)
if (d == j['source']) {
lab = j['unit'];
}
})
return data[0][d] + ' ' + '<span style="font-size:10pt">' + lab + '<span>';
})
makeActive(buttons.filter(function(d) {
return d == initGas
}))
}
function makeGraphs(trace, data) {
data.forEach(function(d, i) {
if (d[trace] == undefined) {
d[trace] = null
}
})
// console.log(data)
var svg = d3.select("svg"),
margin = {
top: 20,
right: 80,
bottom: 110,
left: 50
},
margin2 = {
top: 330,
right: 20,
bottom: 30,
left: 50
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
x = d3.scaleTime().range([0, width])
x2 = d3.scaleTime().range([0, width])
y = d3.scaleLinear().range([height, 0])
y2 = d3.scaleLinear().range([height2, 0])
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([
[0, 0],
[width, height2]
])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([
[0, 0],
[width, height]
])
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoomed);
line = d3.line()
.defined(function(d) {
return d[trace] != null;
})
.x(function(d) {
return x(d.DATE_PST);
})
.y(function(d) {
return y(+d[trace]);
});
line2 = d3.line()
.x(function(d) {
return x2(d.DATE_PST);
})
.y(function(d) {
return y2(+d[trace]);
});
var clip = svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);
thesLine = d3.line()
.x(function(d) {return x(d.DATE_PST);})
.y(function(d) {return y(thres[trace])})
thesLine1 = d3.line()
.x(function(d) {
// console.log(d)
return x(d.DATE_PST);})
.y(function(d) {return y(0)})
var Line_chart = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("clip-path", "url(#clip)");
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr('id', 'context')
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
x.domain(d3.extent(data, d => d.DATE_PST));
y.domain([d3.min(data, d => +d[trace]), d3.max(data, d => +d[trace])]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
yaxe = focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
Line_chart.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.style("stroke", function() {
if (met.includes(trace)) {
c = '#de2d26'
} else {
c = '#2b8cbe'
}
return c
});
threshold = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "focus")
.attr("clip-path", "url(#clip)");
if (trace in thres){
threshold.append('path')
.datum(data)
.attr('d', thesLine);
y.domain([d3.min(data, d => +d[trace]), thres[trace]]);
}else{
threshold.append('path')
.datum(data)
.attr('d', thesLine1);
}
context.append("path")
.datum(data)
.attr("class", "line")
.attr("id", "line2")
.attr("d", line2)
.style("stroke", function() {
if (met.includes(trace)) {
c = '#de2d26'
} else {
c = '#2b8cbe'
}
return c
});;
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
focus1 = focus.append("g")
.attr("class", "focus1")
.style("display", "none");
focus1.append("circle")
.attr("r", 3);
focus1.append("text")
.attr("x", -20)
// .attr("y", -20)
.attr("dy", "-1em");
svg.append("rect")
.attr("class", "zoom")
.attr("id", "overlay")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom)
.on("mouseover", function() {
focus1.style("display", null);
})
.on("mouseout", function() {
focus1.style("display", "none");
})
.on("mousemove", mousemove);
// console.log(colUnits)
un = d3.values(meas).filter(function(vals) {
return vals['source'] == initGas
})
ylab = svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text(colUnits[i_unit-2]); //ugly, hardcoded for now
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0])
i = bisectDate(data, x0, 1)
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.DATE_PST > d1.DATE_PST - x0 ? d1 : d1;
focus1.attr("transform", "translate(" + x(d.DATE_PST) + "," + y(d[trace]) + ")");
focus1.select("text").text(formatMonth(d.DATE_PST))
.append('tspan')
.attr('dy',"1em")
.attr('dx',"-3em")
.text(d[trace]);
// valText = d3.select('.focus1')
// valText.append('tspan')
// .attr('dy',"1em")
// .text(d[trace]);
// focus1
// focus1.select("text").text(d[trace]).append("tspan")
// .attr("x", 10).attr("dy", "1.5em").text(formatTime(d.DATE_PST));
// var bbox = focus1.select("text").node().getBBox();
// var rectWidth = bbox.width + 4
// rect.attr("width", rectWidth).attr("height", bbox.height + 4)
// var mouseOnRight = d3.mouse(this)[0] > (width/2) ? true : false
// var translateX = mouseOnRight ? x(d.DATE_PST) - rectWidth : x(d.DATE_PST);
// focus.attr("transform", "translate(" + translateX + "," + y(d[trace]) + ")");
};
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
Line_chart.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
// d3.select(".selected-date").html(formatTime(t.rescaleX(x2).domain()[0])+' - '+formatTime(t.rescaleX(x2).domain()[1]));
Line_chart.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
}
function updateGraph(trace, data,i_unit) {
data.forEach(function(d) {
if (d[trace] == undefined) {
d[trace] = null
}
})
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0])
i = bisectDate(data, x0, 1)
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.DATE_PST > d1.DATE_PST - x0 ? d1 : d1;
focus1.attr("transform", "translate(" + x(d.DATE_PST) + "," + y(d[trace]) + ")");
focus1.select("text").text(formatMonth(d.DATE_PST))
.append('tspan')
.attr('dy',"1em")
.attr('dx',"-2em")
.text(d[trace]);
};
if (!(trace in thres)){
y.domain([d3.min(data, function(d) {
return +d[trace]}), d3.max(data, function(d) {
return +d[trace]})])
}else{
y.domain([0, d3.max(data, function(d) {
return +d[trace]+5})]);
}
y2.domain(y.domain());
yAxis = d3.axisLeft(y);
yaxe.transition()
.call(yAxis);
un = d3.values(meas).filter(function(vals) {
return vals['source'] == trace
})
console.log(i_unit)
ylab.transition()
.text(colUnits[i_unit])
line = d3.line()
.defined(function(d) {
return d[trace] != null;
})
.x(function(d) {
return x(d.DATE_PST);
})
.y(function(d) {
// console.log(d[trace])
return y(d[trace]);
});
line2 = d3.line()
.x(function(d) {
return x2(d.DATE_PST);
})
.y(function(d) {
return y2(+d[trace]);
});
Line_chart = d3.select("g").transition();
context = d3.select("#context").transition();
// console.log(trace)
Line_chart.select(".line")
.duration(750)
.attr("d", line)
.style("stroke", function(d) {
// console.log(d)
if (met.includes(trace)) {
c = '#de2d26'
} else {
c = '#2b8cbe'
}
return c
});
context.select("#line2")
.duration(750)
.attr("d", line2)
.style("stroke", function(d) {
if (met.includes(trace)) {
c = '#de2d26'
} else {
c = '#2b8cbe'
}
return c
});
thesLine = d3.line()
.x(function(d) {return x(d.DATE_PST);})
.y(function(d) {return y(thres[trace])})
thesLine1 = d3.line()
.x(function(d) {
// console.log(d)
return x(d.DATE_PST);})
.y(function(d) {return y(0)})
if (trace in thres){
threshold.selectAll("path")
.attr('class', 'line1')
.transition()
.duration(1000)
.attr("d", thesLine(data));
}else{
threshold.selectAll("path")
.attr('class', 'out')
.transition()
.duration(1000)
.attr("d", thesLine1(data));
}
d3.select(".zoom")
.on("mousemove", mousemove);
}
<!DOCTYPE html>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<!-- Latest compiled and minified CSS -->
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="main.css">
</head>
<style>
#chart_container {
position: absolute;
left:500px;
top:180px;
/*background-color: rgba(255,255,255,.7);*/
/*padding-bottom: 100px;*/
}
#chart{
/*padding-bottom: 100px;*/
}
#distid {
padding-left:600px;
margin-bottom: -75px;
}
.btn {
border-radius: 0px !important;
transition: linear, ease-in 0.3s !important;
outline-color: blue;
}
.btn:focus {
/*color: white !important;*/
color: black !important;
}
.btn-default {
color: black !important;
/*background: transparent !important;*/
border: black 0px solid !important;
padding: 2% !important;
}
.btn-default:hover {
color: white !important;
background: black !important;
border-color: black !important;
}
.btn-default:focus {
outline: none !important;
text-decoration: none !important;
/*color: black !important;*/
/*color: white !important;*/
}
.btn-default:active {
background: orange !important;
}
.btn-default a {
color: black !important;
}
.btn-default a:focus {
color: red !important;
}
#FORECAST_TODAY, #FORECAST_TONIGHT, #FORECAST_TOMORROW {
pointer-events:none;
}
.controller-button{
padding: 10px;
margin: 10px;
}
.val{
font-size: 22px;
color: steelblue;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.line1 {
fill: none;
stroke: steelblue;
/*stroke-width: 1.5px;*/
}
.line2 {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
#overlay {
fill: none;
pointer-events: all;
}
.focus1 circle {
fill: none;
stroke: steelblue;
}
.line1 {
fill: none;
stroke: #ddd;
stroke-width: 1.5px;
}
.selected-date{
float:right;
}
</style>
<body>
<div class="container-fluid info">
<div class = "date col-xs-8 col-md-12">
<h1 class = "current-cond"></h1>
<h3 class = "current-date"></h3>
<h1 class = "pollutant-name"></h1>
<div class = "container-fluid button"></div>
<div class = "legendSize"></div>
</div>
<!-- <div class = "weather col-xs-4 col-md-4">
<h4 class = "last-date"></h4>
</div> -->
</div>
<p class = "selected-date"></p>
<svg width="960" height="400"></svg>
<div id="chart_container">
<div id="chart"></div>
</div>
<script src="//d3js.org/d3.v4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="graph.js"></script>
</body>
</html>
Data Source Short Name Units
HUMIDITY Humidity %
NO NO ppb
NO_24 NO_24 ppb
NOx NOx (24h) ppb
NOx_24 NOx (24h) ppb
NO2 NO2 ppb
NO2_24 NO2_24 ppb
O3 O3 ppb
O3_8 O3 (8hr) ppb
PM10 PM10 µg/m3
PM10_24 PM10 (24hr) ppb
PM25 PM2.5 µg/m3
PM25_24 PM2.4 (24hr) ppb
SO2 SO2 ppb
SO2_24 SO2_24 ppb
TRS TRS ppb
CO CO ppm
WDIR_VECT Wind Direction °
WSPD_VECT Wind Speed m/s
TEMP_MEAN Temperature °C
PRECIPITATION Precipitation mm
WSPD_SCLR Wind speed m/s
WDIR_UVEC Wind Direction °
BAR_PRESS_HOUR Barometric pressure kPa
AQHI AQHI
FORECAST_TONIGHT Forecast Tonight
FORECAST_TODAY Forecast Today
FORECAST_TOMORROW Forecast Tomorrow
html {
min-width: 1040px;
}
body {
font-family: "Helvetica Neue", Helvetica, sans-serif;
margin: 1em auto 4em auto;
position: relative;
tab-size: 2;
width: 960px;
}
/*h1 {
font-size: 2rem;
font-weight: 300;
padding-bottom: 20px;
}
h2 {
font-size: 1.5rem;
font-weight: 300;
}
h1, h2 {
text-rendering: optimizeLegibility;
}*/
#leftcolumn, #rightcolumn {
float: left;
}
#leftcolumn {
width: 550px;
}
#rightcolumn {
width: 250px;
}
aside {
font-size: small;
left: 780px;
position: absolute;
text-align: right;
width: 180px;
}
p {
line-height: 1.5em;
}
blockquote {
width: 640px;
}
li {
width: 680px;
}
a {
color: steelblue;
}
a:not(:hover) {
text-decoration: none;
}
pre, code, textarea {
font-family: "Menlo", monospace;
line-height: normal;
}
textarea {
font-size: 100%;
}
pre {
border-left: solid 2px #ccc;
padding-left: 18px;
margin: 2em 0 2em -20px;
width: 960px;
overflow-x: auto;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment