Commit a78a9f96 authored by Michał Woźniak's avatar Michał Woźniak
Browse files

basic implementation of case fatality rate

parent d22e6984
......@@ -681,18 +681,31 @@ let calculateDeltas = (data) => {
}
// calculate the deltas
data.data = data.data.map((cur, i, d)=>{
if (i==0) {
cur.new_confirmed = 0;
cur.new_recovered = 0;
cur.new_deaths = 0;
cur.active = 0;
cur.new_active = 0;
cur.cfr = 0
} else {
cur.new_confirmed = cur.confirmed - d[i-1].confirmed
cur.new_recovered = cur.recovered - d[i-1].recovered
cur.new_deaths = cur.deaths - d[i-1].deaths
cur.active = cur.confirmed - (cur.recovered + cur.deaths)
var removed = cur.recovered + cur.deaths
cur.active = cur.confirmed - removed
cur.new_active = cur.active - d[i-1].active
// case fatality ratio
if (removed > 0) {
cur.cfr = cur.deaths / removed
cur.new_cfr = cur.cfr - d[i-1].cfr
} else {
cur.cfr = 0
}
}
return cur;
})
......@@ -1045,6 +1058,11 @@ let selectSite = (e) => {
*/
let chartGuidelineGradient = (chart, dataset) => {
// if the dataset is hidden, we don't need to do anythin
if (chart.data.datasets[dataset].hidden) {
return false;
}
// get the metadata of the chart dataset
// that is, x, y coordinates of points! yay!
var meta = chart.getDatasetMeta(dataset);
......@@ -1224,7 +1242,7 @@ let chart = () => {
legend_opts.labels.usePointStyle = true
// make sure we're using the guideline datasets only
legend_opts.labels.filter = (legendItem, data) => {
return (legendItem.datasetIndex <= 2);
return ( (! legendItem.hidden) && (legendItem.datasetIndex <= 2) );
}
// use the borderColor for the box inside, instead of the gradient
// (which might be barely visible at that point of canvas)
......@@ -1319,6 +1337,17 @@ let updateChartData = (siteSelect) => {
// which data are we looking at
var dataset = document.querySelector('input[type=radio][name=chart-data]:checked').value
// dataset name used for start-at comparisons
if (dataset === 'cfr') {
// when showing CFR data, we want to start at nth confirmed case
// since CFR by definition cannot go above 1
var start_at_dataset = 'confirmed'
// for everything else we're fine with the actual dataset
} else {
var start_at_dataset = dataset
}
// filter the data
var found_start = false
......@@ -1327,7 +1356,7 @@ let updateChartData = (siteSelect) => {
.filter((row, idx) => {
if (found_start) {
return true
} else if ( ( (start_at_date) && ( row.date === start_at_date) ) || (row[dataset] >= start_at) ) {
} else if ( ( (start_at_date) && ( row.date === start_at_date) ) || (row[start_at_dataset] >= start_at) ) {
found_start = true
return true
}
......@@ -1396,6 +1425,10 @@ let updateChartData = (siteSelect) => {
}
/*
* update various chart settings
* based on datasets we have
*/
let updateChartSettings = () => {
// if *any* of the sitesSelects are still fetching data, bail out
......@@ -1409,31 +1442,60 @@ let updateChartSettings = () => {
// get the y-axis type from the controls
theChart.options.scales.yAxes[0].type = document.querySelector('input[type=radio][name=chart-type]:checked').value
// calculate the max value and the x-axis length that make sense
// with reasonable minimums
var max_cases = 100;
var min_cases = 0;
var max_data_points = 20;
theChart.data.datasets.slice(3).forEach((d)=>{
d_max = Math.max(...d.data)
d_min = Math.min(...d.data)
if (d_max > max_cases) {
max_cases = d_max
}
if (d_min < min_cases) {
min_cases = d_min
}
if (d.data.length > max_data_points) {
max_data_points = d.data.length
// which dataset are we using? confirmed, recovered, deaths, active, cfr?
var chart_dataset = document.querySelector('input[type=radio][name=chart-data]:checked').value
// for cfr, this is easy: min=0, max=1, chart_type_factor=1
// also, no guidelines
if (chart_dataset === 'cfr') {
var max_cases = 1;
var min_cases = 0;
var max_data_points = 20;
theChart.data.datasets.slice(3).forEach((d)=>{
if (d.data.length > max_data_points) {
max_data_points = d.data.length
}
})
var chart_type_factor = 1
theChart.data.datasets[0].hidden = true
theChart.data.datasets[1].hidden = true
theChart.data.datasets[2].hidden = true
// for everything else, a bit more involved
// also, guidelines
} else {
// calculate the max value and the x-axis length that make sense
// with reasonable minimums
var max_cases = 100;
var min_cases = 0;
var max_data_points = 20;
theChart.data.datasets.slice(3).forEach((d)=>{
d_max = Math.max(...d.data)
d_min = Math.min(...d.data)
if (d_max > max_cases) {
max_cases = d_max
}
if (d_min < min_cases) {
min_cases = d_min
}
if (d.data.length > max_data_points) {
max_data_points = d.data.length
}
})
// set the chart factor:
// basically, we want a bit of headspace above the highest point on any graph
if (theChart.options.scales.yAxes[0].type == "logarithmic") {
var chart_type_factor = 2
} else {
var chart_type_factor = 1.1
}
})
// make sure guidelines are visible
theChart.data.datasets[0].hidden = false
theChart.data.datasets[1].hidden = false
theChart.data.datasets[2].hidden = false
}
// set the max value
if (theChart.options.scales.yAxes[0].type == "logarithmic") {
var chart_type_factor = 2
} else {
var chart_type_factor = 1.1
}
theChart.options.scales.yAxes[0].ticks.max = Math.round(max_cases * chart_type_factor)
var chart_start_setting = document.querySelector('input[type=radio][name=chart-start]:checked').value
......@@ -1443,8 +1505,7 @@ let updateChartSettings = () => {
var chart_start = (1 * chart_start_setting)
}
// which dataset are we using? confirmed, recovered, deaths, active?
var chart_dataset = document.querySelector('input[type=radio][name=chart-data]:checked').value
// start building the title
theChart.options.title.text = []
// let's start with which data are we displaying, exactly
......@@ -1460,7 +1521,7 @@ let updateChartSettings = () => {
// move the y-axis zero point depending on whether we're showing cumulative or new cases
if (document.querySelector('input[type=radio][name=chart-cases]:checked').value === 'cumulative') {
if (document.querySelector('input[type=radio][name=chart-values]:checked').value === 'absolute') {
if ( (chart_dataset !== "cfr" ) && (document.querySelector('input[type=radio][name=chart-values]:checked').value === 'absolute') ) {
theChart.options.scales.yAxes[0].ticks.min = chart_start
} else {
theChart.options.scales.yAxes[0].ticks.min = 0
......
......@@ -324,6 +324,7 @@
.chart-config-container input#chart-data-recovered:checked ~ .chart-config-group label[for=chart-data-recovered],
.chart-config-container input#chart-data-deaths:checked ~ .chart-config-group label[for=chart-data-deaths],
.chart-config-container input#chart-data-active:checked ~ .chart-config-group label[for=chart-data-active],
.chart-config-container input#chart-data-cfr:checked ~ .chart-config-group label[for=chart-data-cfr],
.chart-config-container input#chart-type-logarithmic:checked ~ .chart-config-group label[for=chart-type-logarithmic],
.chart-config-container input#chart-type-linear:checked ~ .chart-config-group label[for=chart-type-linear],
.chart-config-container input#chart-cases-cumulative:checked ~ .chart-config-group label[for=chart-cases-cumulative],
......@@ -437,6 +438,7 @@
<input type="radio" id="chart-data-recovered" name="chart-data" value="recovered"/>
<input type="radio" id="chart-data-deaths" name="chart-data" value="deaths"/>
<input type="radio" id="chart-data-active" name="chart-data" value="active"/>
<input type="radio" id="chart-data-cfr" name="chart-data" value="cfr"/>
<input type="radio" id="chart-type-logarithmic" name="chart-type" value="logarithmic" checked="checked"/>
<input type="radio" id="chart-type-linear" name="chart-type" value="linear"/>
<input type="radio" id="chart-cases-cumulative" name="chart-cases" value="cumulative" checked="checked"/>
......@@ -454,6 +456,7 @@
<label for="chart-data-recovered">recoveries</label>
<label for="chart-data-deaths">deaths</label>
<label for="chart-data-active">active cases</label>
<label for="chart-data-cfr">case fatality rate</label>
</div>
<div class="chart-config-group">
<p>Scale:</p>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment