Public
Edited
May 30
1 fork
Insert cell
Insert cell
svg = {
const svg = d3.select(DOM.svg(width + (hexRadius * 5), height));
const g = svg.append('g').attr('transform', `translate(${hexRadius*4},${hexRadius * 10})`);

// Add model run time labels
const modelRuns = g.selectAll('.run-time')
.data( points.slice(0, 24 ))
.join('text')
.text((d, i) => {
return moment.utc(mostRecentModelRunData).subtract( mapColumns, 'hour').add( i, 'hour').format( 'YYYY-MM-DD HH')
})
.attr('class', 'run-time')
.attr('x', d => d.x - hexRadius)
.attr('y', -hexRadius)
.attr('transform', d => ( 'rotate(60 ' + (d.x - hexRadius ) + ' ' + -hexRadius + ')'))
.style('text-anchor', 'end')
.style('fill', 'black')
.style('stroke', 'none');

// Add row labels
const rowLabels = g.selectAll('.row-label')
.data( dataArray[0] ).enter()
.append('text')
.text((d,i) => i === 0 ? 'Observed Dst' : 'T+' + i + ' difference' )
.attr('class', 'row-label')
.attr('x', (d,i) => ( mapColumns * hexRadius * SQRT3 ) + (i * (hexRadius * SQRT3 / 2)))
.attr('y', (d,i) => (i * hexRadius * 1.5) + 3)
.style('fill', 'black')
.style('stroke', 'none')
.style('text-anchor', 'start')
// Draw each hexagon
const hexagons = g.selectAll('.hexagon')
.data(hexbin(points))
.join('path')
.attr('class', 'hexagon')
.style('stroke', 'white')
.style('stroke-width', 1.5)
.style('fill', (d) => {
return d.y === 0 ? 'goldenrod' : isNaN(d[0].difference) ? 'gainsboro' : color(d[0].difference);
})
.style('fill-opacity', d => isNaN(d[0].difference) ? 1 : 0.6)
.attr('d', (d, i) => {
return 'M' + d.x + ',' + d.y + hexbin.hexagon()
});

// Add difference value to hexagon content
const values = g.selectAll('.value')
.data( points ).enter()
.append('text')
.text(d => isNaN(d.difference) ? d.value : d.difference )
.attr('class', 'value')
.attr('x', d => d.x.toFixed(0))
.attr('y', d => d.y + 3)
.style('fill', d => isNaN(d.difference) ? 'goldenrod' : 'black')
.style('stroke', 'white')
.style('stroke-width', 0.1)
.style('text-anchor', 'middle')
.on('mouseover', hover)
.on('mouseout', leave);
// Mouseover a value
function hover(d) {
hexagons.style( 'fill-opacity', h => !isNaN(d.difference) && d.time === h[0].time ? 1 : 0.6)
.style('stroke-width', h => !isNaN(d.difference) && d.time === h[0].time ? 5 : 1.5);
modelRuns.style( 'fill', m => d.time === m.time ? 'goldenrod' : 'black');
d3.select(this)
.transition().duration(10)
.text( d => d.value)
.style('fill', 'goldenrod')
.style('cursor', 'default')
}

// Mouseout function
function leave(d) {
hexagons.style( 'fill-opacity', 0.6)
.style('stroke-width', 1.5);
modelRuns.style( 'fill', 'black');
d3.select(this)
.transition().duration(500)
.style('fill-opacity', 0.6)
.style('fill', d => d.difference ? 'black' : 'goldenrod' )
.text( d => isNaN(d.difference) ? d.value : d.difference)
}
return svg.node()
}
Insert cell
Insert cell
points = {
const rowArray = Array.from(Array(mapRows).keys());
const colArray = Array.from(Array(mapColumns).keys());
const pointsArray = rowArray.reduce( ( aggregator, row ) => {
colArray.forEach( col => {
const rowOffset = Math.floor( row / 2);
const colWidth = hexRadius * SQRT3;
const rowHeight = hexRadius * 1.5;
const x = (rowOffset * colWidth) + ( row%2 === 1 ? (col * colWidth) + (( colWidth ) / 2) : (col * colWidth ));
const y = row * rowHeight;
const timestamp = moment.utc(modelRuns[col]).valueOf();
const relativeTimestamp = moment.utc(modelRuns[col + rowOffset]).valueOf();
const dstValue = dstData[timestamp];
const modelValue = dataArray[col][row] ? dataArray[col][row][1].toFixed(0) : null;
const difference = row === 0 ? dstValue : dstData[relativeTimestamp] - modelValue;
aggregator.push( {
x: x,
y: y,
time: relativeTimestamp,
difference: difference,
value: modelValue
} );
});
return aggregator;
}, []);
console.log({ pointsArray });
return pointsArray;
}
Insert cell
Insert cell
// width = Math.ceil(mapColumns * hexRadius * SQRT3 + hexRadius)
width = 850
Insert cell
// height = Math.ceil(mapRows * 1.5 * hexRadius + 0.5 * hexRadius)
height = 400
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
modelRuns = Array.from(Array(mapColumns).keys()).map( value => moment.utc( mostRecentModelRunData ).clone().subtract( mapColumns, 'hours').add( value, 'hours').format('YYYY-MM-DDTHH:00:00'))
Insert cell
mostRecentModelRun = (await fetch('https://livedst-api.dev.swx-trec.com/livedst_latest')).json()
Insert cell
dstRequest = (await fetch('https://lasp.colorado.edu/space-weather-portal/latis/dap/kyoto_dst_index_service.jsond?time,dst&time%3E%3D' + modelRuns[0] )).json()
Insert cell
dstData = dstRequest.kyoto_dst_index_service.data.reduce( (aggregator, data ) => {
aggregator[data[0]] = data[1];
return aggregator;
}, {})
Insert cell
dataArray = [ getValuesOnly(thing0), getValuesOnly(thing1), getValuesOnly(thing2),getValuesOnly(thing3), getValuesOnly(thing4), getValuesOnly(thing5), getValuesOnly(thing6), getValuesOnly(thing7), getValuesOnly(thing8), getValuesOnly(thing9), getValuesOnly(thing10), getValuesOnly(thing11), getValuesOnly(thing12), getValuesOnly(thing13), getValuesOnly(thing14), getValuesOnly(thing15), getValuesOnly(thing16), getValuesOnly(thing17), getValuesOnly(thing18), getValuesOnly(thing19), getValuesOnly(thing20), getValuesOnly(thing21), getValuesOnly(thing22), getValuesOnly(thing23) ]
Insert cell
newDataArray = [ getValuesOnly(thing0)]
Insert cell
Insert cell
Insert cell
thing1 = (await dataPromises[1]).json();
Insert cell
thing2 = (await dataPromises[2]).json();
Insert cell
thing3 = (await dataPromises[3]).json();
Insert cell
thing4 = (await dataPromises[4]).json();
Insert cell
thing5 = (await dataPromises[5]).json();
Insert cell
thing6 = (await dataPromises[6]).json();
Insert cell
thing7 = (await dataPromises[7]).json();
Insert cell
thing8 = (await dataPromises[8]).json();
Insert cell
thing9 = (await dataPromises[9]).json();
Insert cell
thing10 = (await dataPromises[10]).json();
Insert cell
thing11 = (await dataPromises[11]).json();
Insert cell
thing12 = (await dataPromises[12]).json();
Insert cell
thing13 = (await dataPromises[13]).json();
Insert cell
thing14 = (await dataPromises[14]).json();
Insert cell
thing15 = (await dataPromises[15]).json();
Insert cell
thing16 = (await dataPromises[16]).json();
Insert cell
thing17 = (await dataPromises[17]).json();
Insert cell
thing18 = (await dataPromises[18]).json();
Insert cell
thing19 = (await dataPromises[19]).json();
Insert cell
thing20 = (await dataPromises[20]).json();
Insert cell
thing21 = (await dataPromises[21]).json();
Insert cell
thing22 = (await dataPromises[22]).json();
Insert cell
thing23 = (await dataPromises[23]).json();
Insert cell
Insert cell
getValuesOnly = (response) => response.predictions.data;
Insert cell
mostRecentModelRunData = mostRecentModelRun.predictions.data[0][0]
Insert cell
Insert cell
Insert cell
hexbin = d3.hexbin()
.radius(hexRadius)
.x(d => d.x)
.y(d => d.y)
Insert cell
Insert cell
Insert cell
moment = require('moment');
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more