-
-
Save ix4/e97bd109b6d527fd9b5da9c3ba376b36 to your computer and use it in GitHub Desktop.
Perspective Workspace for COVID-19 U.S. Data
This file contains hidden or 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: apache-2.0 | |
height: 800 |
This file contains hidden or 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 name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective-workspace/umd/perspective-workspace.js"></script> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective-viewer-datagrid/umd/perspective-viewer-datagrid.js"></script> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective-viewer-d3fc/umd/perspective-viewer-d3fc.js"></script> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective/umd/perspective.js"></script> | |
<link rel='stylesheet' href="https://perspective-covid.herokuapp.com/static/perspective-workspace/umd/material.css"> | |
<style> | |
body { | |
display: flex; | |
flex-direction: column; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
} | |
</style> | |
</head> | |
<body> | |
<perspective-workspace id="workspace"></perspective-workspace> | |
<script> | |
const state_data = async (websocket) => { | |
const worker = perspective.worker(); | |
// Get a proxy for a view named "state_data_source", registered on | |
// the server with a reciprocal call to `host_view()`. | |
// No data is transferred, `view` is a virtual handle for data on | |
// the server. | |
const view = websocket.open_view('state_data_source'); | |
// Create a `table` from this, owned by the local WebWorker. | |
// Data is transferred from `view` to the local WebWorker, both | |
// the current state and all future updates, as Arrows. | |
return worker.table(view); | |
}; | |
const county_data = async (websocket) => { | |
const worker = perspective.worker(); | |
// Get a proxy for a view named "state_data_source", registered on | |
// the server with a reciprocal call to `host_view()`. | |
// No data is transferred, `view` is a virtual handle for data on | |
// the server. | |
const view = websocket.open_view('county_data_source'); | |
// Create a `table` from this, owned by the local WebWorker. | |
// Data is transferred from `view` to the local WebWorker, both | |
// the current state and all future updates, as Arrows. | |
return worker.table(view); | |
}; | |
window.addEventListener("load", async () => { | |
const websocket = perspective.websocket("wss://perspective-covid.herokuapp.com/ws"); | |
const state_datasource = await state_data(websocket); | |
const county_datasource = await county_data(websocket) | |
window.workspace.tables.set("state", state_datasource); | |
window.workspace.tables.set("county", county_datasource); | |
// const scatter_config = window.getPlugin("d3_xy_scatter"); | |
// scatter_config.max_columns = 500; | |
// const area_config = window.getPlugin("d3_y_area"); | |
// area_config.max_columns = 500; | |
// area_config.max_cells = 100000; | |
const line_config = window.getPlugin("d3_y_line"); | |
line_config.max_cells = 100000; | |
line_config.max_columns = 5000; | |
await window.workspace.restore({ | |
sizes: [0.25, 0.75], | |
detail: { | |
main: { | |
type: "split-area", | |
orientation: "vertical", | |
children: [ | |
{ | |
type: "split-area", | |
orientation: "horizontal", | |
children: [ | |
{ | |
type: "tab-area", | |
widgets: ["StateConfirmedWidget", "StatePopulationWidget"], | |
currentIndex: 0 | |
}, | |
{ | |
type: "tab-area", | |
widgets: ["StateDeathsWidget"], | |
currentIndex: 0 | |
} | |
], | |
sizes: [0.5, 0.5] | |
}, | |
{ | |
type: "split-area", | |
orientation: "horizontal", | |
children: [ | |
{ | |
type: "tab-area", | |
widgets: ["CountyGridWidget"], | |
currentIndex: 0 | |
}, | |
{ | |
type: "tab-area", | |
widgets: ["CountyConfirmedWidget"], | |
currentIndex: 0 | |
}, | |
{ | |
type: "tab-area", | |
widgets: ["CountyDeathsWidget"], | |
currentIndex: 0 | |
} | |
], | |
sizes: [0.33, 0.33, 0.33] | |
} | |
], | |
sizes: [0.5, 0.5] | |
} | |
}, | |
master: { | |
widgets: ["MasterStateWidget"] | |
}, | |
mode: "globalFilters", | |
viewers: { | |
MasterStateWidget: { | |
plugin: "datagrid", | |
name: "Confirmed & Deaths by State", | |
table: "state", | |
"computed-columns": ["'Deaths' % 'Confirmed' as 'Fatality Rate (%)'"], | |
columns: ["Fatality Rate (%)", "Confirmed", "Deaths"], | |
"row-pivots": ["State Name"], | |
aggregates: { | |
"Confirmed": "high", | |
"Deaths": "high", | |
"Fatality Rate (%)": "avg" | |
}, | |
sort: [["Confirmed", "desc"]], | |
}, | |
StateConfirmedWidget: { | |
name: "Cases since March 1st (by state)", | |
table: "state", | |
columns: ["Confirmed"], | |
"row-pivots": ["Date"], | |
"filters": [["Date", ">", "03/01/2020"]], | |
"column-pivots": ["State Name"], | |
plugin: "d3_y_line", | |
plugin_config: { | |
legend: { | |
left: "80px", | |
top: "15px" | |
} | |
}, | |
}, | |
StateDeathsWidget: { | |
name: "Deaths since March 1st (by state)", | |
table: "state", | |
columns: ["Deaths"], | |
"row-pivots": ["Date"], | |
"filters": [["Date", ">", "03/01/2020"]], | |
"column-pivots": ["State Name"], | |
plugin: "d3_y_line", | |
plugin_config: { | |
legend: { | |
left: "80px", | |
top: "15px" | |
} | |
}, | |
}, | |
StatePopulationWidget: { | |
name: "Cases as % of state population", | |
table: "state", | |
plugin: "datagrid", | |
columns: ["Cases % Population", "Confirmed", "Population (2019 Estimate)"], | |
aggregates: { | |
"Confirmed": "high", | |
"Cases % Population": "avg", | |
"Population (2019 Estimate)": "high" | |
}, | |
"row-pivots": ["State Name"], | |
"computed-columns": ["'Confirmed' % 'Population (2019 Estimate)' as 'Cases % Population'"] | |
}, | |
CountyConfirmedWidget: { | |
name: "Cases since March 1st (by county)", | |
table: "county", | |
columns: ["Confirmed"], | |
"row-pivots": ["Date"], | |
"column-pivots": ["Location"], | |
"filters": [["Date", ">", "03/01/2020"]], | |
plugin: "d3_y_line", | |
"computed-columns": ['concat_comma("County", "State") as "Location"', "'Deaths' % 'Confirmed'"], | |
plugin_config: { | |
legend: { | |
left: "80px", | |
top: "15px" | |
} | |
}, | |
"computed-columns": ['concat_comma("County", "State") as "Location"'], | |
}, | |
CountyDeathsWidget: { | |
name: "Deaths since March 1st (by county)", | |
table: "county", | |
columns: ["Deaths"], | |
"row-pivots": ["Date"], | |
"column-pivots": ["Location"], | |
"filters": [["Date", ">", "03/01/2020"]], | |
plugin: "d3_y_line", | |
"computed-columns": ['concat_comma("County", "State") as "Location"', "'Deaths' % 'Confirmed'"], | |
plugin_config: { | |
legend: { | |
left: "80px", | |
top: "15px" | |
} | |
}, | |
"computed-columns": ['concat_comma("County", "State") as "Location"'], | |
}, | |
CountyGridWidget: { | |
plugin: "datagrid", | |
name: "Confirmed & Deaths (by county)", | |
table: "county", | |
columns: ["Confirmed", "Deaths"], | |
"row-pivots": ["Location"], | |
sort: [["Confirmed", "desc"]], | |
aggregates: { | |
"Confirmed": "high", | |
"Deaths": "high" | |
}, | |
"computed-columns": ['concat_comma("County", "State") as "Location"'], | |
}, | |
} | |
}); | |
// Custom formatting for the datagrid - display percentages with a `%` | |
for (const viewer of document.getElementById("workspace").querySelectorAll("perspective-viewer")) { | |
viewer.addEventListener("perspective-datagrid-after-update", event => { | |
const datagrid = event.detail; | |
for (const td of datagrid.get_tds()) { | |
const metadata = datagrid.get_meta(td); | |
if (metadata.column.includes("%") && typeof metadata.value === "number") { | |
const pct = metadata.value.toFixed(4).toString(); | |
td.textContent = pct + "%"; | |
} else { | |
td.style.display = "table-cell"; | |
} | |
} | |
}); | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment