Skip to content

Commit

Permalink
Merge pull request #87 from RhoInc/v2.2.1-dev
Browse files Browse the repository at this point in the history
Safety Histogram v2.2.1
  • Loading branch information
jwildfire authored Oct 24, 2018
2 parents 214d5c2 + 3f3a485 commit 2e190fc
Show file tree
Hide file tree
Showing 11 changed files with 1,358 additions and 98 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
MIT License
Copyright (c) 2016-2017 [Rho Inc.](http://www.rhoworld.com)
Copyright (c) 2016-2018 [Rho Inc.](http://www.rhoworld.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
68 changes: 32 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# Saftey Histogram

![alt tag](https://user-images.githubusercontent.com/31038805/33951165-3e6299dc-dffc-11e7-82c6-0ffd133f42ac.gif)

## Overview

Safety Histogram is a JavaScript library, built using Webcharts ([1](https://github.com/RhoInc/Webcharts), [2](https://github.com/RhoInc/webcharts-wrapper-boilerplate)), that creates an interactive histogram showing the distribution of lab measures, vital signs, and other measures related to safety in clinical trials. A typical chart created with safety-histogram looks like this:

![Example](https://user-images.githubusercontent.com/31038805/33951675-9edaeb42-dffd-11e7-8bed-71988d7092a2.gif)
Expand All @@ -19,10 +17,7 @@ Users can:
* Filter the histogram for selected criteria, and see an updated chart (optional)
* Show or hide normal ranges for the selected measure (optional)



## Typical Usage

In the simplest case, using a dataset matching all default requirements, the chart can be created with a single line of code.

```javascript
Expand All @@ -32,40 +27,41 @@ safetyHistogram('#chartLocation', {}).init(data);
The code to load a comma-delimited data set and initialize the customized chart, with filters and simple data mappings, looks like this:

```javascript
const settings =
{filters:
[ {value_col: 'VISIT', label: 'Visit'},
, {value_col: 'SITEID', label: 'Site ID'},
, {value_col: 'SEX', label: 'Sex'},
, {value_col: 'RACE', label: 'Race'}
]
,start_value: 'POTASSIUM'
,details: [
{value_col: 'USUBJID' , label: 'Subject ID'},
{value_col: 'SITEID' , label: 'Site ID' },
{value_col: 'SEX' , label: 'Sex' },
{value_col: 'RACE' , label: 'Race' },
{value_col: 'VISIT' , label: 'Visit' },
{value_col: 'DY' , label: 'Study Day' },
{value_col: 'STNRLO' , label: 'LLN' },
{value_col: 'STRESN' , label: 'Result'},
{value_col: 'STNRHI' , label: 'ULN' },
{value_col: 'STRESU' , label: 'Units' }
};

d3.csv('../data/ADBDS.csv', function(data) {
safetyHistogram('#safety-histogram .content', settings).init(data);
});
const settings = {
start_value: 'POTASSIUM',
filters: [
{value_col: 'VISIT' , label: 'Visit'},
{value_col: 'SITEID' , label: 'Site ID'},
{value_col: 'SEX' , label: 'Sex'},
{value_col: 'RACE' , label: 'Race'}
],
details: [
{value_col: 'USUBJID' , label: 'Subject ID'},
{value_col: 'SITEID' , label: 'Site ID'},
{value_col: 'SEX' , label: 'Sex'},
{value_col: 'RACE' , label: 'Race'},
{value_col: 'VISIT' , label: 'Visit'},
{value_col: 'DY' , label: 'Study Day'},
{value_col: 'STNRLO' , label: 'LLN'},
{value_col: 'STRESN' , label: 'Result'},
{value_col: 'STNRHI' , label: 'ULN'},
{value_col: 'STRESU' , label: 'Units'}
]
};

d3.csv(
'https://rawgit.com/RhoInc/viz-library/master/data/safetyData/ADBDS.csv',
function(data) {
safetyHistogram('body', settings).init(data);
}
);
```

Click [here](https://rhoinc.github.io/viz-library/examples/0008-safetyExplorer-default/safety-histogram/) to open an interactive example.
Click [here](https://rhoinc.github.io/safety-histogram/test-page/) to open an interactive example.

## Links

- [Interactive Example](https://rhoinc.github.io/viz-library/examples/0008-safetyExplorer-default/safety-histogram/)
- [Configuration](https://github.com/RhoInc/safety-histogram/wiki/Configuration)
- [Interactive Example](https://rhoinc.github.io/safety-histogram/test-page/)
- [Configuration](https://github.com/RhoInc/safety-histogram/wiki/Configuration)
- [API](https://github.com/RhoInc/safety-histogram/wiki/API)
- [Technical Documentation](https://github.com/RhoInc/safety-histogram/wiki/Technical-Documentation)
- [Technical Documentation](https://github.com/RhoInc/safety-histogram/wiki/Technical-Documentation)
- [Data Guidelines](https://github.com/RhoInc/safety-histogram/wiki/Data-Guidelines)


49 changes: 20 additions & 29 deletions build/safetyHistogram.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory(require('webcharts'), require('d3')))
? (module.exports = factory(require('d3'), require('webcharts')))
: typeof define === 'function' && define.amd
? define(['webcharts', 'd3'], factory)
: (global.safetyHistogram = factory(global.webCharts, global.d3));
})(this, function(webcharts, d3$1) {
? define(['d3', 'webcharts'], factory)
: (global.safetyHistogram = factory(global.d3, global.webCharts));
})(this, function(d3, webcharts) {
'use strict';

if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, 'assign', {
value: function assign(target, varArgs) {
// .length of function is 2
'use strict';

if (target == null) {
// TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
Expand Down Expand Up @@ -292,7 +289,7 @@
function countParticipants() {
var _this = this;

this.populationCount = d3$1
this.populationCount = d3
.set(
this.raw_data.map(function(d) {
return d[_this.config.id_col];
Expand Down Expand Up @@ -326,7 +323,7 @@
this.raw_data = clean;

//Attach array of continuous measures to chart object.
this.measures = d3$1
this.measures = d3
.set(
this.raw_data.map(function(d) {
return d[_this.config.measure_col];
Expand Down Expand Up @@ -357,7 +354,7 @@
' ] filter has been removed because the variable does not exist.'
);
} else {
var levels = d3$1
var levels = d3
.set(
_this.raw_data.map(function(d) {
return d[input.value_col];
Expand Down Expand Up @@ -502,7 +499,7 @@
this.measure_data = this.raw_data.filter(function(d) {
return d[_this.config.measure_col] === _this.currentMeasure;
});
this.measure_domain = d3$1.extent(this.measure_data, function(d) {
this.measure_domain = d3.extent(this.measure_data, function(d) {
return +d[_this.config.value_col];
});
}
Expand Down Expand Up @@ -612,26 +609,21 @@
function onDatatransform() {}

// Takes a webcharts object creates a text annotation giving the
// number and percentage of observations shown in the current view
// inputs:
// chart - a webcharts chart object
// id_col - a column name in the raw data set (chart.raw_data) representing the observation of interest
// id_unit - a text string to label the units in the annotation (default = "participants")
// selector - css selector for the annotation

function updateParticipantCount(chart, selector, id_unit) {
//count the number of unique ids in the current chart and calculate the percentage
var currentObs = d3$1
var currentObs = d3
.set(
chart.filtered_data.map(function(d) {
return d[chart.config.id_col];
})
)
.values().length;
var percentage = d3$1.format('0.1%')(currentObs / chart.populationCount);
var percentage = d3.format('0.1%')(currentObs / chart.populationCount);

//clear the annotation
var annotation = d3$1.select(selector);
d3$1
var annotation = d3.select(selector);
d3
.select(selector)
.selectAll('*')
.remove();
Expand Down Expand Up @@ -733,7 +725,7 @@

//Reduce bin opacity and highlight selected bin.
bins.attr('fill-opacity', 0.5);
d3$1.select(this).attr('fill-opacity', 1);
d3.select(this).attr('fill-opacity', 1);
})
.on('mouseover', function(d) {
//Update footnote.
Expand Down Expand Up @@ -767,7 +759,7 @@
else chart.wrap.selectAll('.normalRange').remove();

normalRangeControl.on('change', function() {
chart.config.displayNormalRange = d3$1
chart.config.displayNormalRange = d3
.select(this)
.select('input')
.property('checked');
Expand All @@ -783,7 +775,7 @@
canvas.selectAll('.normalRange').remove();

//Capture distinct normal ranges in filtered data.
var normalRanges = d3$1
var normalRanges = d3
.nest()
.key(function(d) {
return d[chart.config.normal_col_low] + ',' + d[chart.config.normal_col_high];
Expand All @@ -792,7 +784,7 @@
return d.length;
})
.entries(chart.filtered_data);
var currentRange = d3$1.extent(chart.filtered_data, function(d) {
var currentRange = d3.extent(chart.filtered_data, function(d) {
return +d[chart.config.value_col];
});
//Sort normal ranges so larger normal ranges plot beneath smaller normal ranges.
Expand Down Expand Up @@ -856,7 +848,7 @@
? '' + chart.filtered_data[0][chart.config.unit_col]
: '') +
(' (' +
d3$1.format('%')(d.values / chart.filtered_data.length) +
d3.format('%')(d.values / chart.filtered_data.length) +
' of records)')
);
});
Expand Down Expand Up @@ -888,7 +880,7 @@

function hideDuplicateXaxisTickLabels() {
this.svg.selectAll('.x.axis .tick').each(function(d, i) {
var tick = d3$1.select(this);
var tick = d3.select(this);
var value = +d;
var text = +tick.select('text').text();
tick.style('display', value === text ? 'block' : 'none');
Expand Down Expand Up @@ -918,8 +910,7 @@
function onDestroy() {}

//polyfills
//settings
//webcharts

function safetyHistogram(element, settings) {
//Define chart.
var mergedSettings = Object.assign({}, defaultSettings, settings);
Expand Down
Loading

0 comments on commit 2e190fc

Please sign in to comment.