Skip to content

Commit

Permalink
Merge pull request #382 from MoTrPAC/369_JZ_Dawg_Pac_Pheno_Data_Analysis
Browse files Browse the repository at this point in the history
Connects to #369. PASS1AC-06 phenotype data analysis (initial phase).
  • Loading branch information
jimmyzhen authored Dec 19, 2024
2 parents 2edd123 + d13a7f2 commit 1363adc
Show file tree
Hide file tree
Showing 25 changed files with 1,486 additions and 193 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"react-wordcloud": "^1.2.7",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"simple-statistics": "^7.8.7",
"tocbot": "^4.25.0",
"victory": "37.0.2",
"vis-network-react": "DinerIsmail/vis-network-react"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import { useSelector } from 'react-redux';
import SectionWeightDistribution from './sectionWeightDistribution';
import SectionLactateChange from './sectionLactateChange';
import SectionRatWork from './sectionRatWork';

/**
* Function component for the summary statistics category of PASS1AC-06 phenotypic data analysis
*
* @param {array} phenoData Curated phenotypic data
*
* @returns JSX element of the summary statistics category
*/
function CategorySummaryStatistics() {
const analysisState = useSelector((state) => state.analysis);

return (
<div className="w-100 analysis-category-content-container">
<h2>Summary Statistics</h2>
<p>
In this section, various summary statistics and visualizations that
explore key variables across the phenotypic data are presented. The
analysis covers weight distribution, electric shocks (both number
and duration), distance covered during the acute test, and lactate
changes due to exercise. Each variable is visualized through a
combination of boxplots, histograms, and density plots, broken down
by relevant factors such as sex, phase, and intervention group.
Additionally, we analyze the time taken to freeze tissues, including
comparisons across different groups and a detailed look at the order
in which tissues were frozen for each animal. These visualizations
help to identify patterns and trends within the phenotypic data.
</p>
{/* weight distribution section */}
{analysisState.pass1ac06AnalysisCategoryOptions.summaryStatistics.weight_distribution && (
<SectionWeightDistribution />
)}
{/* lactate change section */}
{analysisState.pass1ac06AnalysisCategoryOptions.summaryStatistics.lactate_change && (
<SectionLactateChange />
)}
{/* rat work section */}
{analysisState.pass1ac06AnalysisCategoryOptions.summaryStatistics.rat_work && (
<SectionRatWork />
)}
</div>
);
}

export default CategorySummaryStatistics;
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { useMemo } from 'react';
import {
COLORS,
defaultChartOptions,
allBoxPlotDataByPhaseSexIntervention,
allScatterPlotDataByPhaseSex,
} from '../sharedLib';
import Chart from '../chartWrapper';

/**
* Renders summary statistics plots for lactate change
*
* @returns JSX representation of Highcharts plots for rat work - boxplots and scatter plots
*/
function PlotLactateChange() {
// Base chart options
const baseChartOptions = defaultChartOptions('Intervention', 'Lactate Change', 'Lactate Change: {point.y}');

// Function to collect lactate change data for box plot
const getLactateChangeData = (data) => data.map((item) => parseFloat(item.lactate_change));
const boxPlotData = useMemo(() => allBoxPlotDataByPhaseSexIntervention(getLactateChangeData), []);

// Scatter plot data for pass1a and pass1c (both male and female)
const scatterData = useMemo(() => allScatterPlotDataByPhaseSex(getLactateChangeData), []);

// Highcharts options for the plots
const chartOptions = useMemo(() => {
const createChartOptions = (gender, titleText) => {
const allData = [
...boxPlotData[`pass1a${gender}Acute`],
...boxPlotData[`pass1c${gender}Acute`],
...boxPlotData[`pass1a${gender}Control`],
...boxPlotData[`pass1c${gender}Control`],
...scatterData.pass1a[gender.toLowerCase()].map(([, y]) => y),
...scatterData.pass1c[gender.toLowerCase()].map(([, y]) => y),
];

const minValue = Math.min(...allData);
const maxValue = Math.max(...allData);
const padding = 0.1 * (maxValue - minValue);

return {
...baseChartOptions,
title: {
align: 'left',
style: { fontSize: '1.5rem' },
text: titleText,
},
xAxis: {
...baseChartOptions.xAxis,
categories: ['Acute', 'Control'],
},
yAxis: {
...baseChartOptions.yAxis,
min: minValue - padding,
max: maxValue + padding,
},
series: [
{
name: 'PASS1A-06 Lactate Change Distribution',
type: 'boxplot',
legendSymbol: 'areaMarker',
data: [
boxPlotData[`pass1a${gender}Acute`],
boxPlotData[`pass1a${gender}Control`],
],
fillColor: COLORS.pass1a.fill,
},
{
name: 'PASS1C-06 Lactate Change Distribution',
type: 'boxplot',
legendSymbol: 'areaMarker',
data: [
boxPlotData[`pass1c${gender}Acute`],
boxPlotData[`pass1c${gender}Control`],
],
fillColor: COLORS.pass1c.fill,
},
{
name: 'PASS1A-06 Scatter',
type: 'scatter',
data: scatterData.pass1a[gender.toLowerCase()],
color: COLORS.pass1a.scatter,
jitter: { x: 0.1 },
showInLegend: false,
},
{
name: 'PASS1C-06 Scatter',
type: 'scatter',
data: scatterData.pass1c[gender.toLowerCase()],
color: COLORS.pass1c.scatter,
jitter: { x: 0.1 },
showInLegend: false,
},
],
};
};

return {
male: createChartOptions('Male', 'Distribution of LACTATE CHANGE by INTERVENTION and MALE'),
female: createChartOptions('Female', 'Distribution of LACTATE CHANGE by INTERVENTION and FEMALE'),
};
}, [baseChartOptions, boxPlotData, scatterData]);

return (
<div className="col-lg-11 h-90">
<Chart options={chartOptions.male} className="phenotype-plot-container" />
<Chart options={chartOptions.female} className="phenotype-plot-container" />
</div>
);
}

export default PlotLactateChange;
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useMemo } from 'react';
import {
COLORS,
defaultChartOptions,
allBoxPlotDataByPhaseSexIntervention,
allScatterPlotDataByPhaseSex,
} from '../sharedLib';
import Chart from '../chartWrapper';

/**
* Renders summary statistics plots for rat work
*
* @returns JSX representation of Highcharts plots for rat work - boxplots and scatter plots
*/
function PlotRatWork() {
// Base chart options
const baseChartOptions = defaultChartOptions('Intervention', 'Work', 'Work: {point.y} joules');

// Function to collect lactate change data for box plot
const getRatWorkData = (data) => data.map((item) => {
const weight = parseInt(item.weight, 10) / 1000;
const distance = parseInt(item.distance, 10);
return weight * distance * 0.087 * 9.80665;
});
const boxPlotData = useMemo(() => allBoxPlotDataByPhaseSexIntervention(getRatWorkData), []);

// Scatter plot data for pass1a and pass1c (both male and female)
const scatterData = useMemo(() => allScatterPlotDataByPhaseSex(getRatWorkData), []);

// Highcharts options for the plots
const chartOptions = useMemo(() => {
const createChartOptions = (gender, titleText) => {
const allData = [
...boxPlotData[`pass1a${gender}Acute`],
...boxPlotData[`pass1c${gender}Acute`],
...boxPlotData[`pass1a${gender}Control`],
...boxPlotData[`pass1c${gender}Control`],
...scatterData.pass1a[gender.toLowerCase()].map(([, y]) => y),
...scatterData.pass1c[gender.toLowerCase()].map(([, y]) => y),
];

const minValue = Math.min(...allData);
const maxValue = Math.max(...allData);
const padding = 0.1 * (maxValue - minValue);

return {
...baseChartOptions,
title: {
align: 'left',
style: { fontSize: '1.5rem' },
text: titleText,
},
xAxis: {
...baseChartOptions.xAxis,
categories: ['Acute', 'Control'],
},
yAxis: {
...baseChartOptions.yAxis,
min: minValue - padding,
max: maxValue + padding,
},
series: [
{
name: 'PASS1A-06 Work Distribution',
type: 'boxplot',
legendSymbol: 'areaMarker',
data: [
boxPlotData[`pass1a${gender}Acute`],
boxPlotData[`pass1a${gender}Control`],
],
fillColor: COLORS.pass1a.fill,
},
{
name: 'PASS1C-06 Work Distribution',
type: 'boxplot',
legendSymbol: 'areaMarker',
data: [
boxPlotData[`pass1c${gender}Acute`],
boxPlotData[`pass1c${gender}Control`],
],
fillColor: COLORS.pass1c.fill,
},
{
name: 'PASS1A-06 Scatter',
type: 'scatter',
data: scatterData.pass1a[gender.toLowerCase()],
color: COLORS.pass1a.scatter,
jitter: { x: 0.1 },
showInLegend: false,
},
{
name: 'PASS1C-06 Scatter',
type: 'scatter',
data: scatterData.pass1c[gender.toLowerCase()],
color: COLORS.pass1c.scatter,
jitter: { x: 0.1 },
showInLegend: false,
},
],
};
};

return {
male: createChartOptions('Male', 'Distribution of WORK by INTERVENTION and MALE'),
female: createChartOptions('Female', 'Distribution of WORK by INTERVENTION and FEMALE'),
};
}, [baseChartOptions, boxPlotData, scatterData]);

return (
<div className="col-lg-11 h-90">
<Chart options={chartOptions.male} className="phenotype-plot-container" />
<Chart options={chartOptions.female} className="phenotype-plot-container" />
</div>
);
}

export default PlotRatWork;
Loading

0 comments on commit 1363adc

Please sign in to comment.