Skip to content

Commit

Permalink
add race, hide unwanted sections
Browse files Browse the repository at this point in the history
  • Loading branch information
Amy Chen committed Oct 30, 2024
1 parent 7c9dcd5 commit da1ac61
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 10 deletions.
24 changes: 22 additions & 2 deletions src/server/Model/Cohort/DemographicAggregator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public class DemographicAggregator
readonly Dictionary<string,int> Sex = new Dictionary<string, int>();
readonly Dictionary<string,int> Gender = new Dictionary<string, int>();
readonly Dictionary<string,int> Age = new Dictionary<string, int>();
readonly Dictionary<string,int> Race = new Dictionary<string, int>();

readonly NihRaceEthnicityBuckets NihRaceEthnicity = new NihRaceEthnicityBuckets();

Expand Down Expand Up @@ -141,6 +142,7 @@ public DemographicStatistics Aggregate()
RecordReligion(patient);
RecordSex(patient);
RecordGender(patient);
RecordRace(patient);
RecordNih(patient);
RecordAge(patient);
RecordCoccur(patient);
Expand All @@ -157,10 +159,10 @@ public DemographicStatistics Aggregate()
{
BinarySplitData = new List<BinarySplitPair> {
GenderSplit,
VitalSplit,
// VitalSplit,
AARPSplit,
HispanicSplit,
MarriedSplit,
// MarriedSplit,
CoccurSplit,
MethcurSplit,
OpicurSplit,
Expand All @@ -174,6 +176,7 @@ public DemographicStatistics Aggregate()
LanguageByHeritageData = LanguageByHeritage,
ReligionData = Religion,
GenderData = Gender,
RaceData = Race,
NihRaceEthnicityData = NihRaceEthnicity,
SexData = Sex,
AgeData = Age
Expand Down Expand Up @@ -447,6 +450,23 @@ void RecordSex(PatientDemographic patient)
Sex.Add(sex, 1);
}

void RecordRace(PatientDemographic patient)
{
if (string.IsNullOrEmpty(patient.Race))
{
return;
}

var race = patient.Race.ToLowerInvariant();

if (Race.ContainsKey(race))
{
Race[race]++;
return;
}
Race.Add(race, 1);
}

readonly static string[] adultAgeBuckets = { "<20", "20-29", "30-39", "40-49", "50-59", "60-69", ">=70"};
void RecordAge(PatientDemographic patient)
{
Expand Down
1 change: 1 addition & 0 deletions src/server/Model/Cohort/DemographicStatistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class DemographicStatistics
public Dictionary<string,int> SexData { get; set; }
public Dictionary<string,int> GenderData { get; set; }
public Dictionary<string,int> AgeData { get; set; }
public Dictionary<string,int> RaceData { get; set; }
public NihRaceEthnicityBuckets NihRaceEthnicityData { get; set; }
}
}
23 changes: 15 additions & 8 deletions src/ui-client/src/components/Visualize/AggregateDemographics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Age} from './Age';
import { Binary } from './Binary';
import { Gender} from './Gender';
import { LanguageByHeritage } from './LanguageByHeritage';
import { Race } from "./Race";
import { Religion } from './Religion';
import { Sex } from "./Sex";
import { NihRaceEthnicityGenderTable } from './NihRaceEthnicityGenderTable';
Expand All @@ -28,7 +29,7 @@ export default class AggregateDemographics extends React.PureComponent<Props> {
private delayIncrementMs = 600;

public render() {
const { ageByGenderData, binarySplitData, languageByHeritageData, religionData, nihRaceEthnicityData, genderData, sexData, ageData } = this.props.cohort.visualization.demographics;
const { ageByGenderData, binarySplitData, languageByHeritageData, religionData, nihRaceEthnicityData, genderData, sexData, ageData, raceData } = this.props.cohort.visualization.demographics;
const colWidth = this.props.width / 2;
const getDelay = (i: number): number => i * this.delayIncrementMs;
return (
Expand Down Expand Up @@ -84,25 +85,31 @@ export default class AggregateDemographics extends React.PureComponent<Props> {
</Row>
<Row>
<Col lg={6} md={12} className="visualization-languagebyheritage-container">
<SectionHeader headerText="Ethnic Heritage by Language" />
<LanguageByHeritage
<SectionHeader headerText="Race/Ethnicity" />
{/* <LanguageByHeritage
bucketset={languageByHeritageData}
delay={getDelay(2)}
height={this.props.height}
width={colWidth}
/>
/> */}
<Race
counts={raceData}
delay={getDelay(2)}
height={this.props.height}
width={colWidth}
></Race>
</Col>
<Col lg={6} md={12} className="visualization-ataglance-container">
{/* <Col lg={6} md={12} className="visualization-ataglance-container">
<SectionHeader headerText="Religious Beliefs" />
<Religion
counts={religionData}
delay={getDelay(3)}
height={this.props.height}
width={colWidth}
/>
</Col>
</Col> */}
</Row>
<Row>
{/* <Row>
<Col md={12} className="visualization-nih">
<SectionHeader
headerText="NIH Race, Ethnicity, and Gender"
Expand All @@ -112,7 +119,7 @@ export default class AggregateDemographics extends React.PureComponent<Props> {
<Col lg={{ size: 8, order: 2, offset: 2 }} md={12}>
<NihRaceEthnicityGenderTable data={nihRaceEthnicityData} />
</Col>
</Row>
</Row> */}
</Container>
);
}
Expand Down
130 changes: 130 additions & 0 deletions src/ui-client/src/components/Visualize/Race.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/* Copyright (c) 2022, UW Medicine Research IT, University of Washington
* Developed by Nic Dobbins and Cliff Spital, CRIO Sean Mooney
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import React from "react";
import {
Bar,
BarChart,
ResponsiveContainer,
XAxis,
YAxis,
LabelList,
Cell,
} from "recharts";
import { visualizationConfig } from "../../config/visualization";
import { PatientCountMap } from "../../models/cohort/DemographicDTO";

interface Props {
counts: PatientCountMap;
delay: number;
height: number;
width: number;
}

interface State {
showAll: boolean;
useDelay: boolean;
}

export class Race extends React.PureComponent<Props, State> {
private className = "visualization-race";
private maxWidth = 800;
private defaultDataLength = 20;

public constructor(props: Props) {
super(props);
this.state = {
showAll: false,
useDelay: true,
};
}

public render() {
const config = visualizationConfig.demographics.race;
const { height, width, counts, delay } = this.props;
const { showAll, useDelay } = this.state;
const c = this.className;
const del = useDelay ? delay : 0;
const w = width > this.maxWidth ? this.maxWidth : width;

if (!counts) return <div style={{ margin: "24px" }}>No data available</div>;
let data = Object.entries(counts)
.map(([key, value]) => ({ key, value }))
.sort((a, b) => (a.value > b.value ? 0 : 1));
const len = data.length;

if (!showAll) {
data = data.slice(0, this.defaultDataLength);
}

return (
<div className={`${c}-column`} style={{ height, width: w }}>
{/* Show all toggle */}
{len > this.defaultDataLength && (
<div className="visualization-showall-toggle">
<span
className={`visualization-showall false ${
showAll ? "" : "selected"
}`}
onClick={this.handleShowAllToggleClick.bind(null, false)}
>{`Show top ${this.defaultDataLength} only`}</span>
<span
className={`visualization-showall true ${
showAll ? "selected" : ""
}`}
onClick={this.handleShowAllToggleClick.bind(null, true)}
>{`Show all ${len}`}</span>
</div>
)}

{/* Chart */}
<div style={{ height }}>
<ResponsiveContainer>
<BarChart
data={data}
margin={{ top: 30, right: 30, left: 10, bottom: 5 }}
layout={"vertical"}
>
<XAxis type="number" allowDecimals={false} hide={true} />
<YAxis dataKey="key" type="category" interval={0} width={150} />
<Bar
animationBegin={del}
barSize={config.barSize}
dataKey="value"
isAnimationActive={true}
>
{data.map((d, i) => (
<Cell key={d.key} fill={this.color(i, config.colors)} />
))}
<LabelList
dataKey="value"
formatter={this.formatNumber}
position="right"
/>
<LabelList dataKey="key" position="left" />
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
</div>
);
}

private formatNumber = (val: any) => val.toLocaleString();

private color = (i: number, colors: string[]): string => {
const last = colors.length - 1;
if (i <= last) {
return colors[i];
}
return colors[i - Math.floor(i / last) * last - 1];
};

private handleShowAllToggleClick = (showAll: boolean) => {
this.setState({ showAll, useDelay: false });
};
}
4 changes: 4 additions & 0 deletions src/ui-client/src/config/visualization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export const visualizationConfig = {
barSize: 32,
colors: ["#00BCD4", '#8bc34a', '#f44336', '#e57373', '#FFA726']
},
race: {
barSize: 32,
colors: ["#087E8B", "#0B3954", "#F48498", "#B4ADEA", "#713E5A", "#C6C5B9"]
},
age: {
barSize: 28,
colors: [ "rgb(255, 152, 150)", "rgb(148, 103, 189)", "rgb(197, 176, 213)", "rgb(140, 86, 75)", "rgb(196, 156, 148)", "rgb(227, 119, 194)", "rgb(247, 182, 210)", "rgb(127, 127, 127)", "rgb(199, 199, 199)",
Expand Down

0 comments on commit da1ac61

Please sign in to comment.