Skip to content

Commit

Permalink
feat: basic histogram and storybook, including version that queries b…
Browse files Browse the repository at this point in the history
…ackend

...using recharts library which is already part
of this portal.

Also fixed CohortsOverlapDiagram storybook
  • Loading branch information
pieterlukasse committed Dec 16, 2022
1 parent 1ca364e commit caf40ed
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ const selectedControlCohort = {

export const SuccessCase = Template.bind({});
SuccessCase.args = {
sourceId: 123,
selectedStudyPopulationCohort: selectedStudyPopulationCohort,
selectedCaseCohort: selectedCaseCohort,
selectedControlCohort: selectedControlCohort,
selectedCovariates: [],
selectedDichotomousCovariates: [],
outcome: null
};
SuccessCase.parameters = {
// msw mocking:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import {
BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip
} from 'recharts';
import PropTypes from 'prop-types';

//TODO - add legend, auto-scaling, sorting, etc
const Histogram = ({
data,
xAxisDataKey,
barDataKey,
chartWidth,
chartHeight,
barColor
}) => (
<BarChart
width={chartWidth}
height={chartHeight}
data={data}
>
<XAxis dataKey={xAxisDataKey}/>
<YAxis />
<Tooltip />
<CartesianGrid strokeDasharray='3 3' />
<Bar dataKey={barDataKey} fill={barColor} />
</BarChart>
);

Histogram.propTypes = {
data: PropTypes.array.isRequired,
xAxisDataKey: PropTypes.string.isRequired,
barDataKey: PropTypes.array.isRequired,
chartWidth: PropTypes.number,
chartHeight: PropTypes.number,
barColor: PropTypes.string
};

Histogram.defaultProps = {
chartWidth: 500,
chartHeight: 300,
barColor: '#8884d8'
};

export default Histogram;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import Histogram from './Histogram';

export default {
title: "Tests3/GWASV2/Histogram_Recharts",
component: Histogram,
};

const Template = (args) => <Histogram {...args} />;

export const FirstStepActive = Template.bind({});
FirstStepActive.args = {
data: [
{ ageBin: '1-2', patients: 10000 },
{ ageBin: 4, patients: 500 },
{ ageBin: 3, patients: 12250 },
{ ageBin: 'bin 2', patients: 5000 },
{ ageBin: '1-2', patients: 10000 },
{ ageBin: 4, patients: 500 },
{ ageBin: 3, patients: 12250 },
{ ageBin: 'bin 2', patients: 5000 },
{ ageBin: '1-2', patients: 10000 },
{ ageBin: 4, patients: 500 },
{ ageBin: 3, patients: 12250 },
{ ageBin: 'bin 2', patients: 5000 },
{ ageBin: '1-2', patients: 10000 },
{ ageBin: 4, patients: 500 },
{ ageBin: 3, patients: 12250 },
{ ageBin: 'bin 2', patients: 5000 },
],
xAxisDataKey: 'ageBin',
barDataKey: 'patients',
barColor: 'darkblue'
};

export const SecondStepError = Template.bind({});
SecondStepError.args = {
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useQuery } from 'react-query';
import { Spin } from 'antd';
import { fetchHistogramInfo, queryConfig } from '../../../Shared/cohortMiddlewareApi';
import Histogram from './Histogram';
import { useSourceContext } from '../../../Shared/Source';

const PhenotypeHistogram = ({
selectedStudyPopulationCohort,
selectedCovariates,
outcome,
selectedConceptId,
}) => {
const { source } = useSourceContext();
const sourceId = source; // TODO - change name of source to sourceId for clarity
const { data, status } = useQuery(
[
'gethistogramforcurrentlyselectedconcept',
sourceId,
selectedStudyPopulationCohort,
selectedCovariates,
outcome,
selectedConceptId
],
() => fetchHistogramInfo(
sourceId,
selectedStudyPopulationCohort,
selectedCovariates,
outcome,
selectedConceptId
),
queryConfig,
);

if (status === 'error') {
return <React.Fragment>Error getting data for diagram</React.Fragment>;
}
if (status === 'loading') {
return <Spin />;
}
const histogramArgs = {
data: data.bins,
xAxisDataKey: 'start',
barDataKey: 'nr_persons',
barColor: 'darkblue'
};
return <Histogram {...histogramArgs} />;
};

PhenotypeHistogram.propTypes = {
selectedStudyPopulationCohort: PropTypes.object.isRequired,
selectedCovariates: PropTypes.array,
outcome: PropTypes.object,
selectedConceptId: PropTypes.number.isRequired,
};

PhenotypeHistogram.defaultProps = {
selectedCovariates: [],
outcome: null,
};

export default PhenotypeHistogram;
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { rest } from 'msw';
import PhenotypeHistogram from './PhenotypeHistogram';
import { SourceContextProvider } from '../../../Shared/Source';

export default {
title: 'Tests3/GWASV2/PhenotypeHistogram',
component: PhenotypeHistogram,
};

const mockedQueryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
},
});

const Template = (args) => (
<QueryClientProvider client={mockedQueryClient}>
<SourceContextProvider>
<PhenotypeHistogram {...args} />
</SourceContextProvider>
</QueryClientProvider>
);

const selectedStudyPopulationCohort = {
cohort_definition_id: 25,
cohort_name: 'Mock population ',
size: 4000,
};


const currentSelection = {
concept_id: 2000006886,
concept_name: 'Attribute1',
variable_type: 'concept',
};


const selectedCovariates = [
{
variable_type: 'custom_dichotomous',
provided_name: 'providednamebyuser',
cohort_ids: [12, 32],
},
{
variable_type: 'custom_dichotomous',
cohort_ids: [1, 2],
provided_name: 'dichotomous test1',
},
{
variable_type: 'concept',
concept_id: 2000006887,
concept_name: 'concept name',
},
];

export const SuccessCase = Template.bind({});
SuccessCase.args = {
selectedStudyPopulationCohort: selectedStudyPopulationCohort,
selectedCovariates: selectedCovariates,
outcome: null,
selectedConceptId: currentSelection.concept_id
};
SuccessCase.parameters = {
// msw mocking:
msw: {
handlers: [
rest.post(
//histogram/by-source-id/${sourceId}/by-cohort-definition-id/${cohortId}/by-histogram-concept-id/${currentSelection.concept_id}`;
'http://:cohortmiddlewarepath/cohort-middleware/histogram/by-source-id/:sourceid/by-cohort-definition-id/:cohortdefinitionId/by-histogram-concept-id/:conceptId',
(req, res, ctx) => {
const { cohortmiddlewarepath } = req.params;
const { cohortdefinitionId } = req.params;
return res(
ctx.delay(1100),
ctx.json({
bins: [
{start: 1, end: 10, nr_persons: 100},
{start: 10, end: 20, nr_persons: 200},
{start: 20, end: 30, nr_persons: 300},
{start: 30, end: 40, nr_persons: 400},
{start: 40, end: 50, nr_persons: 500},
{start: 50, end: 60, nr_persons: 400},
{start: 60, end: 70, nr_persons: 350},
{start: 70, end: 80, nr_persons: 100},
{start: 80, end: 90, nr_persons: 50},
],
})
);
}
),
],
},
};

export const ErrorCase = Template.bind({});
ErrorCase.args = {
selectedStudyPopulationCohort: selectedStudyPopulationCohort,
selectedCovariates: selectedCovariates,
outcome: null,
selectedConceptId: currentSelection.concept_id
};
// mock endpoint failure:
ErrorCase.parameters = {
msw: {
handlers: [
rest.post(
'http://:cohortmiddlewarepath/cohort-middleware/histogram/by-source-id/:sourceid/by-cohort-definition-id/:cohortdefinitionId/by-histogram-concept-id/:conceptId',
(req, res, ctx) => res(ctx.delay(800), ctx.status(403))
),
],
},
};
21 changes: 21 additions & 0 deletions src/Analysis/GWASV2/Shared/cohortMiddlewareApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,27 @@ export const fetchSimpleOverlapInfo = async (
return getOverlapStats.json();
};

export const fetchHistogramInfo = async (
sourceId,
cohortId,
selectedCovariates,
outcome,
selectedConceptId
) => {
const variablesPayload = {
variables: [...selectedCovariates, outcome],
};
const endPoint = `${cohortMiddlewarePath}histogram/by-source-id/${sourceId}/by-cohort-definition-id/${cohortId}/by-histogram-concept-id/${selectedConceptId}`;
const reqBody = {
method: 'POST',
credentials: 'include',
headers,
body: JSON.stringify(variablesPayload),
};
const requestResponse = await fetch(endPoint, reqBody);
return requestResponse.json();
};

export const fetchConceptStatsByHareSubset = async (
cohortDefinitionId,
subsetCovariates,
Expand Down

0 comments on commit caf40ed

Please sign in to comment.