From 17deca74a28f49a9565f1a0e618c890486a6fc75 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:27:21 -0800 Subject: [PATCH 01/27] Convert this component to a parent component with tabs containing child components of pass1b and pass1a pheno data analysis --- src/AnalysisPage/pass1b06PhenotypeAnimal.jsx | 211 +++++-------------- 1 file changed, 56 insertions(+), 155 deletions(-) diff --git a/src/AnalysisPage/pass1b06PhenotypeAnimal.jsx b/src/AnalysisPage/pass1b06PhenotypeAnimal.jsx index f87fd21f..68d3321c 100644 --- a/src/AnalysisPage/pass1b06PhenotypeAnimal.jsx +++ b/src/AnalysisPage/pass1b06PhenotypeAnimal.jsx @@ -1,140 +1,73 @@ import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; import { Helmet } from 'react-helmet'; import PageTitle from '../lib/ui/pageTitle'; -import WeightGainPlot from './plots/weightGain'; -import BodyFatChangePlot from './plots/bodyFatChange'; -import VO2MaxChangePlot from './plots/vo2MaxChange'; -import LactateChangePlot from './plots/lactateChange'; -import PhenotypePlotControls from './plots/phenotypePlotControls'; -import AnalysisActions from './analysisActions'; +import PhenotypePass1b06Rats from './Phenotype/pass1b06Rats'; +import PhenotypePass1a06Rats from './Phenotype/pass1a06Rats'; /** * Functional component to render animal pass1b-06 phenotype data visualization * * @return {Object} JSX representation of the animal phenotype data visualization */ -function Pass1b06PhenotypeAnimal({ - weightPlot, - bodyFatPlot, - vo2Plot, - lactatePlot, - toggleWeightPlot, - toggleBodyFatPlot, - toggleVo2Plot, - toggleLactatePlot, -}) { +function Pass1b06PhenotypeAnimal() { return (
- Endurance Trained Young Adult Rats Phenotypic Data - MoTrPAC Data Hub + Phenotypic Data Analysis - MoTrPAC Data Hub - -
-
-
- Examine the effect of training through a variety of phenotypic data - collected from the Endurance Exercise Training young adult (6{' '} - months) rats. Input: Sex, - Weight, % Body Fat and VO2 Max. + +
+ {/* nav tabs */} +
    +
  • + +
  • +
  • + +
  • +
+ {/* tab panes */} +
+
+
-
-
-
-
-
-
- -
-
- Effect of training on body weight - - PASS1B 6-Month - -
-
-
-
- -
-
-
-
-
-
-
-
- -
-
- Effect of training on body fat - - PASS1B 6-Month - -
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
- Effect of training on VO2 Max - - PASS1B 6-Month - -
-
-
-
- -
-
-
-
-
-
-
-
- -
-
- Effect of training on blood lactate - - PASS1B 6-Month - -
-
-
-
- -
-
-
+
+
@@ -142,36 +75,4 @@ function Pass1b06PhenotypeAnimal({ ); } -Pass1b06PhenotypeAnimal.propTypes = { - weightPlot: PropTypes.string, - bodyFatPlot: PropTypes.string, - vo2Plot: PropTypes.string, - lactatePlot: PropTypes.string, - toggleWeightPlot: PropTypes.func.isRequired, - toggleBodyFatPlot: PropTypes.func.isRequired, - toggleVo2Plot: PropTypes.func.isRequired, - toggleLactatePlot: PropTypes.func.isRequired, -}; - -Pass1b06PhenotypeAnimal.defaultProps = { - weightPlot: 'one_week_program', - bodyFatPlot: 'one_week_program', - vo2Plot: 'one_week_program', - lactatePlot: 'one_week_program', -}; - -const mapStateToProps = (state) => ({ - ...state.analysis, -}); - -const mapDispatchToProps = (dispatch) => ({ - toggleWeightPlot: (weightPlot) => dispatch(AnalysisActions.toggleWeightPlot(weightPlot)), - toggleBodyFatPlot: (bodyFatPlot) => dispatch(AnalysisActions.toggleBodyFatPlot(bodyFatPlot)), - toggleVo2Plot: (vo2Plot) => dispatch(AnalysisActions.toggleVo2Plot(vo2Plot)), - toggleLactatePlot: (lactatePlot) => dispatch(AnalysisActions.toggleLactatePlot(lactatePlot)), -}); - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Pass1b06PhenotypeAnimal); +export default Pass1b06PhenotypeAnimal; From 44e8ebc61f3c6437e04a9d3081360970052a0928 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:30:30 -0800 Subject: [PATCH 02/27] Initial commit of new pass1b pheno data analysis component --- src/AnalysisPage/Phenotype/pass1b06Rats.jsx | 168 ++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/pass1b06Rats.jsx diff --git a/src/AnalysisPage/Phenotype/pass1b06Rats.jsx b/src/AnalysisPage/Phenotype/pass1b06Rats.jsx new file mode 100644 index 00000000..a98c1546 --- /dev/null +++ b/src/AnalysisPage/Phenotype/pass1b06Rats.jsx @@ -0,0 +1,168 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import AnalysisActions from '../analysisActions'; +import WeightGainPlot from '../plots/weightGain'; +import BodyFatChangePlot from '../plots/bodyFatChange'; +import VO2MaxChangePlot from '../plots/vo2MaxChange'; +import LactateChangePlot from '../plots/lactateChange'; +import PhenotypePlotControls from '../plots/phenotypePlotControls'; + +function PhenotypePass1b06Rats({ + weightPlot, + bodyFatPlot, + vo2Plot, + lactatePlot, + toggleWeightPlot, + toggleBodyFatPlot, + toggleVo2Plot, + toggleLactatePlot, +}) { + return ( +
+
+
+ Examine the effect of training through a variety of phenotypic data + collected from the Endurance Exercise Training young adult (6 + {' '} + months) rats. + {' '} + Input: + {' '} + Sex, + Weight, % Body Fat and VO2 Max. +
+
+
+
+
+
+
+ +
+
+ Effect of training on body weight + + PASS1B 6-Month + +
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+ Effect of training on body fat + + PASS1B 6-Month + +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+ Effect of training on VO2 Max + + PASS1B 6-Month + +
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+ Effect of training on blood lactate + + PASS1B 6-Month + +
+
+
+
+ +
+
+
+
+
+
+ ); +} + +PhenotypePass1b06Rats.propTypes = { + weightPlot: PropTypes.string, + bodyFatPlot: PropTypes.string, + vo2Plot: PropTypes.string, + lactatePlot: PropTypes.string, + toggleWeightPlot: PropTypes.func.isRequired, + toggleBodyFatPlot: PropTypes.func.isRequired, + toggleVo2Plot: PropTypes.func.isRequired, + toggleLactatePlot: PropTypes.func.isRequired, +}; + +PhenotypePass1b06Rats.defaultProps = { + weightPlot: 'one_week_program', + bodyFatPlot: 'one_week_program', + vo2Plot: 'one_week_program', + lactatePlot: 'one_week_program', +}; + +const mapStateToProps = (state) => ({ + ...state.analysis, +}); + +const mapDispatchToProps = (dispatch) => ({ + toggleWeightPlot: (weightPlot) => dispatch(AnalysisActions.toggleWeightPlot(weightPlot)), + toggleBodyFatPlot: (bodyFatPlot) => dispatch(AnalysisActions.toggleBodyFatPlot(bodyFatPlot)), + toggleVo2Plot: (vo2Plot) => dispatch(AnalysisActions.toggleVo2Plot(vo2Plot)), + toggleLactatePlot: (lactatePlot) => dispatch(AnalysisActions.toggleLactatePlot(lactatePlot)), +}); + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(PhenotypePass1b06Rats); From 7b052895db7d71bce52ed93dd846dea54a9819d0 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:31:14 -0800 Subject: [PATCH 03/27] Initial commit of new pass1a-06 pheno data analysis wrapper component --- src/AnalysisPage/Phenotype/pass1a06Rats.jsx | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/pass1a06Rats.jsx diff --git a/src/AnalysisPage/Phenotype/pass1a06Rats.jsx b/src/AnalysisPage/Phenotype/pass1a06Rats.jsx new file mode 100644 index 00000000..3b6b55bb --- /dev/null +++ b/src/AnalysisPage/Phenotype/pass1a06Rats.jsx @@ -0,0 +1,33 @@ +import React from 'react'; +import AnalysisCategoryNavigation from './Components/Pass1ac-06/analysisCategoryNavigation'; +import CategorySummaryStatistics from './Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics'; +import pass1ac06Data from './pass1ac-animal_pheno.json'; + +/** + * Functional component for PASS1AC-06 phenotypic data analysis visualization + * + * @return JSX element of the PASS1AC-06 phenotypic data analysis + */ +function PhenotypePass1a06Rats() { + return ( +
+
+
+ This analysis aims to investigate the phenotypic data collected from the + MoTrPAC PASS1A/1C study, focusing on key variables that may impact + differential analysis results. Understanding these variables is crucial + for ensuring that our statistical models accurately reflect the biological + processes underlying exercise response and adaptation. +
+
+
+ {/* analysis category navigation component */} + + {/* content of analysis categories */} + +
+
+ ); +} + +export default PhenotypePass1a06Rats; From 88a0c1f422b1cc547c95f32f6d6c7b50dc3474f8 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:34:31 -0800 Subject: [PATCH 04/27] Initial commit of pass1a-06 pheno data analysis box and scatter plot components for summary statistics --- .../SummaryStatistics/plotLactateChange.jsx | 113 ++++++++++++++++ .../SummaryStatistics/plotRatWork.jsx | 117 ++++++++++++++++ .../plotWeightDistribution.jsx | 126 ++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx new file mode 100644 index 00000000..1d01e65d --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx @@ -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 ( +
+ + +
+ ); +} + +export default PlotLactateChange; diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx new file mode 100644 index 00000000..8f135a9c --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx @@ -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 ( +
+ + +
+ ); +} + +export default PlotRatWork; diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx new file mode 100644 index 00000000..e01575a5 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx @@ -0,0 +1,126 @@ +import React, { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import { + COLORS, + defaultChartOptions, + allBoxPlotDataByPhaseSexIntervention, + allScatterPlotDataByPhaseSex, +} from '../sharedLib'; +import Chart from '../chartWrapper'; + +/** + * Renders summary statistics plots for weight disctribution + * + * @returns JSX representation of Highcharts plots for rat work - boxplots and scatter plots + */ +function PlotWeightDistribution() { + const analysisState = useSelector((state) => state.analysis); + const { intervention, phase, sex } = analysisState.pass1ac06PlotDisplayOptions; + + // Base chart options + const baseChartOptions = defaultChartOptions('Intervention', 'Weight', 'Weight: {point.y} grams'); + + // Function to collect lactate change data for box plot + const getWeightData = (data) => data.map((item) => parseFloat(item.weight, 10)); + const boxPlotData = useMemo(() => allBoxPlotDataByPhaseSexIntervention(getWeightData), []); + + // Scatter plot data for pass1a and pass1c (both male and female) + const scatterData = useMemo(() => allScatterPlotDataByPhaseSex(getWeightData), []); + + // conditionally render x-axis categories based on intervention + const xAxisCategories = () => { + const { acute, control } = intervention; + const categories = []; + if (acute) categories.push('Acute'); + if (control) categories.push('Control'); + return categories.length ? categories : ['Acute', 'Control']; + }; + + // 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 Weight Distribution', + type: 'boxplot', + legendSymbol: 'areaMarker', + data: [ + boxPlotData[`pass1a${gender}Acute`], + boxPlotData[`pass1a${gender}Control`], + ], + fillColor: COLORS.pass1a.fill, + }, + { + name: 'PASS1C-06 Weight Distribution', + type: 'boxplot', + legendSymbol: 'areaMarker', + data: [ + boxPlotData[`pass1c${gender}Acute`], + boxPlotData[`pass1c${gender}Control`], + ], + fillColor: COLORS.pass1c.fill, + }, + { + name: 'PASS1A-06 Weight Scatter', + type: 'scatter', + data: scatterData.pass1a[gender.toLowerCase()], + color: COLORS.pass1a.scatter, + jitter: { x: 0.1 }, + showInLegend: false, + }, + { + name: 'PASS1C-06 Weight Scatter', + type: 'scatter', + data: scatterData.pass1c[gender.toLowerCase()], + color: COLORS.pass1c.scatter, + jitter: { x: 0.1 }, + showInLegend: false, + }, + ], + }; + }; + + return { + male: createChartOptions('Male', 'Distribution of WEIGHT by INTERVENTION and MALE'), + female: createChartOptions('Female', 'Distribution of WEIGHT by INTERVENTION and FEMALE'), + }; + }, [baseChartOptions, boxPlotData, scatterData.pass1a, scatterData.pass1c]); + + return ( +
+ + +
+ ); +} + +export default PlotWeightDistribution; From 605412136d08c79712594ff1799ff7b4060f6ef3 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:38:44 -0800 Subject: [PATCH 05/27] Initial commit of pass1a-06 pheno data anaylsis section content wrapper components --- .../sectionLactateChange.jsx | 24 +++++++++++ .../SummaryStatistics/sectionRatWork.jsx | 41 +++++++++++++++++++ .../sectionWeightDistribution.jsx | 24 +++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionWeightDistribution.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx new file mode 100644 index 00000000..6f5bd4a8 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import PlotLactateChange from './plotLactateChange'; + +/** + * Function component for lactate change section of summary statistics category + * in the PASS1AC-06 phenotypic data analysis + * + * @param {array} phenoData Curated phenotypic data + * + * @returns JSX element of the lactate change section + */ +function SectionLactateChange() { + return ( +
+

Lactate Change (before / after) Due to Acute Exercise

+
+ {/* phenotpypic data analysis plots */} + +
+
+ ); +} + +export default SectionLactateChange; diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx new file mode 100644 index 00000000..656694a4 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import PlotRatWork from './plotRatWork'; + +/** + * Function component for rat work section of summary statistics category + * in the PASS1AC-06 phenotypic data analysis + * + * @param {array} phenoData Curated phenotypic data + * + * @returns JSX element of the rat work section + */ +function SectionRatWork() { + return ( +
+

Rat Work

+

+ The rats ran on the treadmill set to 5 degrees, which equals an incline of + 8.7%. Therefore, the work is calculated in joules using 8.7% as the slope. +

+

+ Equation - + + Work = (Body weight (g) / 1000) x distance (meters) x 0.087 x9.80665 + +

+

+ Example - + For a rat weighing 0.200 kg running 500 meters: + + Work = 0.200 x 500 x 0.087 x 9.80665 = 85.318 joules + +

+
+ {/* phenotpypic data analysis plots */} + +
+
+ ); +} + +export default SectionRatWork; diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionWeightDistribution.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionWeightDistribution.jsx new file mode 100644 index 00000000..4d5f9f12 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionWeightDistribution.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import PlotWeightDistribution from './plotWeightDistribution'; + +/** + * Function component for weight distribution section of summary statistics category + * in the PASS1AC-06 phenotypic data analysis + * + * @param {array} phenoData Curated phenotypic data + * + * @returns JSX element of the weight distribution section + */ +function SectionWeightDistribution() { + return ( +
+

Weight Distribution

+
+ {/* phenotpypic data analysis plots */} + +
+
+ ); +} + +export default SectionWeightDistribution; From 6cee2dcefd1bd213c1f57ccb3b46c9acb3bc1661 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:40:32 -0800 Subject: [PATCH 06/27] Initial commit of pass1a-06 pheno data analysis plot wrapper component --- .../Components/Pass1ac-06/chartWrapper.jsx | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx new file mode 100644 index 00000000..a7a104e8 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Highcharts from 'highcharts'; +import HighchartsReact from 'highcharts-react-official'; + +// Import order is important! +require('highcharts/highcharts-more')(Highcharts); +require('highcharts/modules/boost')(Highcharts); +require('highcharts/modules/exporting')(Highcharts); +require('highcharts/modules/export-data')(Highcharts); + +/** + * A component to render a Highcharts chart wrapper container. + * @param {Object} options - Options for rendering Highcharts. + * @param {String} className - Class name for HighchartsReact containerProps. + * @returns {JSX.Element} - The rendered JSX object. + */ +function Chart({ options, className }) { + return ( +
+
+
+
+ +
+
+
+
+ ); +} + +Chart.propTypes = { + options: PropTypes.object.isRequired, + className: PropTypes.string.isRequired, +}; + +export default Chart; From 1cee2e80dfac8258afa898192d63ff9ad8a69436 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:42:23 -0800 Subject: [PATCH 07/27] Initial commit of pass1a-06 pheno data analysis plot library of shared codes --- .../Components/Pass1ac-06/sharedLib.js | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js new file mode 100644 index 00000000..723d415a --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js @@ -0,0 +1,175 @@ +import pass1ac06Data from '../../pass1ac-animal_pheno.json'; + +// male data +export const pass1aMaleAcute = pass1ac06Data.filter((item) => item.phase === 'pass1a' && item.sex === 'male' && item.intervention === 'acute'); +export const pass1aMaleControl = pass1ac06Data.filter((item) => item.phase === 'pass1a' && item.sex === 'male' && item.intervention === 'control'); +export const pass1cMaleAcute = pass1ac06Data.filter((item) => item.phase === 'pass1c' && item.sex === 'male' && item.intervention === 'acute'); +export const pass1cMaleControl = pass1ac06Data.filter((item) => item.phase === 'pass1c' && item.sex === 'male' && item.intervention === 'control'); + +// female data +export const pass1aFemaleAcute = pass1ac06Data.filter((item) => item.phase === 'pass1a' && item.sex === 'female' && item.intervention === 'acute'); +export const pass1aFemaleControl = pass1ac06Data.filter((item) => item.phase === 'pass1a' && item.sex === 'female' && item.intervention === 'control'); +export const pass1cFemaleAcute = pass1ac06Data.filter((item) => item.phase === 'pass1c' && item.sex === 'female' && item.intervention === 'acute'); +export const pass1cFemaleControl = pass1ac06Data.filter((item) => item.phase === 'pass1c' && item.sex === 'female' && item.intervention === 'control'); + +export const groupiCategory = [ + 'acute_00.0h_IPE', 'acute_00.5h', 'acute_01.0h', 'acute_04.0h', + 'acute_07.0h', 'acute_24.0h', 'acute_48.0h', 'control_00.0h', + 'control_00.0h_IPE', 'control_00.5h', 'control_04.0h', 'control_07.0h', +]; + +const createGroupiData = (phase, sex) => groupiCategory.reduce((acc, groupi) => { + acc[groupi] = pass1ac06Data.filter((item) => item.phase === phase && item.sex === sex && item.groupi === groupi); + return acc; +}, {}); + +// male groupi data +export const pass1aMaleGroupi = createGroupiData('pass1a', 'male'); +export const pass1cMaleGroupi = createGroupiData('pass1c', 'male'); + +// female groupi data +export const pass1aFemaleGroupi = createGroupiData('pass1a', 'female'); +export const pass1cFemaleGroupi = createGroupiData('pass1c', 'female'); + +// Function to get all box plot data by phase, sex, and each of the groupi categories +export function allBoxPlotDataByPhaseSexGroupi(processData) { + const boxPlotData = {}; + // male groupi data + Object.keys(pass1aMaleGroupi).forEach((groupi) => { + boxPlotData[`pass1aMale${groupi}`] = calculateBoxPlotData(pass1aMaleGroupi[groupi], processData); + }); + Object.keys(pass1cMaleGroupi).forEach((groupi) => { + boxPlotData[`pass1cMale${groupi}`] = calculateBoxPlotData(pass1cMaleGroupi[groupi], processData); + }); + // female groupi data + Object.keys(pass1aFemaleGroupi).forEach((groupi) => { + boxPlotData[`pass1aFemale${groupi}`] = calculateBoxPlotData(pass1aFemaleGroupi[groupi], processData); + }); + Object.keys(pass1cFemaleGroupi).forEach((groupi) => { + boxPlotData[`pass1cFemale${groupi}`] = calculateBoxPlotData(pass1cFemaleGroupi[groupi], processData); + }); + return boxPlotData; +} + +// Function to get all scatter plot data by phase, sex, and each of the groupi categories +export function allScatterPlotDataByPhaseSexGroupi(processData) { + const getScatterPlots = (groupiData, offset) => Object.keys(groupiData).reduce((acc, groupi) => { + acc[groupi] = processData(groupiData[groupi]).map((value, x) => [x + offset, Math.round(value * 1000) / 1000]); + return acc; + }, {}); + + return { + pass1a: { + male: getScatterPlots(pass1aMaleGroupi, -0.15), + female: getScatterPlots(pass1aFemaleGroupi, -0.15), + }, + pass1c: { + male: getScatterPlots(pass1cMaleGroupi, 0.15), + female: getScatterPlots(pass1cFemaleGroupi, 0.15), + }, + }; +} + +// Function to calculate box plot data +function calculateBoxPlotData(rawData, processData) { + const boxPlotData = processData(rawData).sort((a, b) => a - b); + const len = boxPlotData.length; + return [ + boxPlotData[0], // min + boxPlotData[Math.round(len * 0.25)], // q1 + boxPlotData[Math.round(len * 0.5)], // median + boxPlotData[Math.round(len * 0.75)], // q3 + boxPlotData[len - 1], // max + ]; +} + +// Function to get all box plot data by phase, sex, and intervention +export function allBoxPlotDataByPhaseSexIntervention(processData) { + return { + pass1aMaleAcute: calculateBoxPlotData(pass1aMaleAcute, processData), + pass1aMaleControl: calculateBoxPlotData(pass1aMaleControl, processData), + pass1cMaleAcute: calculateBoxPlotData(pass1cMaleAcute, processData), + pass1cMaleControl: calculateBoxPlotData(pass1cMaleControl, processData), + pass1aFemaleAcute: calculateBoxPlotData(pass1aFemaleAcute, processData), + pass1aFemaleControl: calculateBoxPlotData(pass1aFemaleControl, processData), + pass1cFemaleAcute: calculateBoxPlotData(pass1cFemaleAcute, processData), + pass1cFemaleControl: calculateBoxPlotData(pass1cFemaleControl, processData), + }; +} + +// Function to get all scatter plot data by phase, sex, and intervention +export function allScatterPlotDataByPhaseSex(processData) { + const getScatterPlots = (acuteData, controlData) => [processData(acuteData), processData(controlData)]; + + const createScatterData = (acuteData, controlData, offset) => getScatterPlots(acuteData, controlData) + .reduce((acc, data, x) => acc.concat(data.map((value) => [x + offset, Math.round(value * 1000) / 1000])), []); + + return { + pass1a: { + male: createScatterData(pass1aMaleAcute, pass1aMaleControl, -0.15), + female: createScatterData(pass1aFemaleAcute, pass1aFemaleControl, -0.15), + }, + pass1c: { + male: createScatterData(pass1cMaleAcute, pass1cMaleControl, 0.15), + female: createScatterData(pass1cFemaleAcute, pass1cFemaleControl, 0.15), + }, + }; +} + +// Color constants +export const COLORS = { + pass1a: { + fill: '#f9aeac', + scatter: '#84191b', + }, + pass1c: { + fill: '#8ad9db', + scatter: '#191985', + }, +}; + +// Default chart options +export function defaultChartOptions(xAxisTitle, yAxisTitle, scatterTooltipFormat) { + return { + xAxis: { + title: { + text: xAxisTitle, + margin: 10, + style: { fontSize: '1.0rem', fontWeight: 'bold' }, + }, + labels: { style: { fontSize: '0.85rem', fontWeight: 'bold' } }, + }, + yAxis: { + title: { + text: yAxisTitle, + margin: 20, + style: { fontSize: '1.0rem', fontWeight: 'bold' }, + }, + labels: { style: { fontSize: '0.85rem', fontWeight: 'bold' } }, + }, + plotOptions: { + boxplot: { + boxDashStyle: 'Solid', + lineColor: '#000000', + lineWidth: 2, + medianColor: '#000000', + medianDashStyle: 'Solid', + medianWidth: 4, + stemColor: '#000000', + stemDashStyle: 'Solid', + stemWidth: 2, + whiskerColor: '#000000', + whiskerLength: '50%', + whiskerWidth: 3, + }, + scatter: { + jitter: { x: 0.1, y: 0 }, + marker: { radius: 5, symbol: 'circle' }, + tooltip: { pointFormat: scatterTooltipFormat }, + }, + }, + credits: { enabled: false }, + legend: { squareSymbol: true, symbolWidth: 25 }, + exporting: { enabled: true }, + }; +} From 656d5a7d95fa35489a82e252c7f69e29db005426 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:44:45 -0800 Subject: [PATCH 08/27] Initial commit of pass1a-06 pheno data analysis category menu component --- .../Pass1ac-06/analysisCategoryNavigation.jsx | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx new file mode 100644 index 00000000..1d60dcf3 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import AnalysisActions from '../../../analysisActions'; + +const analysisCategories = [ + { + title: 'Summary Statistics', + categoryVal: 'summaryStatistics', + selections: [ + { label: 'Weight Distribution', value: 'weight_distribution' }, + { label: 'Lactate Change (before / after) Due to Acute Exercise', value: 'lactate_change' }, + { label: 'Rat Work', value: 'rat_work' }, + ], + }, + { + title: 'Correlation Analyses', + categoryVal: 'correlationAnalysis', + selections: [ + { label: 'Overall Correlation Matrix', value: 'overall_correlation_matrix' }, + ], + }, +]; + +/** + * Analysis Category Navigation component + * - Displays the analysis categories for the user to select to view + */ +function AnalysisCategoryNavigation() { + const analysisState = useSelector((state) => state.analysis); + const dispatch = useDispatch(); + + return ( +
+
+
+ Analysis Categories +
+
+ {analysisCategories.map((category) => ( +
+
{category.title}
+
+ {category.selections.map((sel) => ( +
+ dispatch( + AnalysisActions.pass1ac06AnalysisCategoryOptionChange( + category.categoryVal, + sel.value, + ), + )} + /> + +
+ ))} +
+
+ ))} +
+
+
+ ); +} + +export default AnalysisCategoryNavigation; From 923a0338c1ff17d9d6a911757c68bae6ca3765c9 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:47:06 -0800 Subject: [PATCH 09/27] Initial commit of pass1a-06 pheno data analysis wrapper component for summary statistics plots --- .../categorySummaryStatistics.jsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx new file mode 100644 index 00000000..a2b952e2 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx @@ -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 ( +
+

Summary Statistics

+

+ 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. +

+ {/* weight distribution section */} + {analysisState.pass1ac06AnalysisCategoryOptions.summaryStatistics.weight_distribution && ( + + )} + {/* lactate change section */} + {analysisState.pass1ac06AnalysisCategoryOptions.summaryStatistics.lactate_change && ( + + )} + {/* rat work section */} + {analysisState.pass1ac06AnalysisCategoryOptions.summaryStatistics.rat_work && ( + + )} +
+ ); +} + +export default CategorySummaryStatistics; From a0ad1181db63b38a32111e0c83129a06d1281ec9 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:51:01 -0800 Subject: [PATCH 10/27] Update styles for pheno data analysis UI changes due to the addition of pass1a-06 --- src/sass/_bootstrapCustom.scss | 6 + src/sass/analysis/_phenotypeAnimal.scss | 151 ++++++++++++++++++------ 2 files changed, 120 insertions(+), 37 deletions(-) diff --git a/src/sass/_bootstrapCustom.scss b/src/sass/_bootstrapCustom.scss index 37161866..6c1b8de3 100644 --- a/src/sass/_bootstrapCustom.scss +++ b/src/sass/_bootstrapCustom.scss @@ -105,3 +105,9 @@ $green: $accent-green !default; } } } + +.nav-pills .nav-link { + background: 0 0; + border: 0; + border-radius: .25rem; +} diff --git a/src/sass/analysis/_phenotypeAnimal.scss b/src/sass/analysis/_phenotypeAnimal.scss index 4bfc6d9a..3d5b0c8a 100644 --- a/src/sass/analysis/_phenotypeAnimal.scss +++ b/src/sass/analysis/_phenotypeAnimal.scss @@ -1,55 +1,132 @@ .analysisPhenotypePage { - .card-container-phenotype-animal { - .card-header { - padding: 1.05rem 1.25rem; - margin-bottom: 0; - background-color: #fff; - border-bottom: 0 solid transparent; + .nav-pills.phenotype-data-nav { + .nav-link { + border-radius: 0; + color: #777; + padding-left: 0.75rem; + padding-right: 0.75rem; - .card-title { - font-size: 1.20rem; + &.active { + color: #000; + background: 0 0 !important; + border-bottom: solid 2px #000; + + .material-icons { + color: $primary; + } + } + + .nav-label { + font-size: 1.15rem; + margin-left: 0.15rem; + } + } + } + + .analysis-phenotype-container.pass1b-06 { + .card-container-phenotype-animal { + .card-header { + padding: 1.05rem 1.25rem; + margin-bottom: 0; + background-color: #fff; + border-bottom: 0 solid transparent; + + .card-title { + font-size: 1.20rem; + } + } + + .badge { + font-size: 0.85rem; + font-weight: 600; + padding: 0.35em 0.4em; + + &.badge-phase { + background-color: #c6c6c6; + } + } + + /* dropdown menus for plot and table */ + .controlPanel { + .controlRow { + .controlLabel { + font-weight: 600; + font-size: 0.85rem; + margin-right: 0.45rem; + white-space: nowrap; + } + + .btn.dropdown-toggle, + button.dropdown-item { + font-size: 0.85rem; + } + } + } + + /* chart.js plot */ + .phenotype-plot { + .weightGainPlot + .bodyFatPlot { + min-height: 65vh; + } + + .remark { + color: $gray; + font-size: 1.0rem; + margin-left: 0.5rem; + margin-right: 0.5rem; + } } } + } + + .analysis-phenotype-container.pass1ac-06 { + .analysis-category-navigation-container { + .panel-header { + font-size: 1.1rem; + } - .badge { - font-size: 0.85rem; - font-weight: 600; - padding: 0.35em 0.4em; + h6 { + font-weight: 600; + } - &.badge-phase { - background-color: #c6c6c6; + .form-check.selection-item { + margin-bottom: 0.5rem; } } - /* dropdown menus for plot and table */ - .controlPanel { - .controlRow { - .controlLabel { - font-weight: 600; - font-size: 0.85rem; - margin-right: 0.45rem; - white-space: nowrap; - } + .analysis-category-content-container { + h2 { + color: $stanford-cardinal-red; + } - .btn.dropdown-toggle, - button.dropdown-item { - font-size: 0.85rem; - } + h3 { + color: $stanford-cardinal-red; + margin-top: 1.5rem; } } - /* chart.js plot */ - .phenotype-plot { - .weightGainPlot - .bodyFatPlot { - min-height: 65vh; + .analysis-plot-display-options-container { + .panel-header { + font-size: 1.1rem; } - .remark { - color: $gray; - font-size: 1.0rem; - margin-left: 0.5rem; - margin-right: 0.5rem; + h6 { + font-weight: 600; + } + + .form-check.selection-item { + margin-bottom: 0; + } + + .form-group.selection-group { + margin-bottom: 0; + } + } + + .phenotype-plot-container { + .highcharts-container { + height: 600px !important; } } } From 0ab010c1f63cfaa189c1fa991a39400a0ec8fbbb Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Wed, 18 Dec 2024 23:58:41 -0800 Subject: [PATCH 11/27] Add support to show/hide pass1a-06 pheno data analysis plots by category --- src/AnalysisPage/analysisActions.js | 10 ++++++++++ src/AnalysisPage/analysisReducer.js | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/AnalysisPage/analysisActions.js b/src/AnalysisPage/analysisActions.js index e8a5e23c..fbaa41c4 100644 --- a/src/AnalysisPage/analysisActions.js +++ b/src/AnalysisPage/analysisActions.js @@ -10,6 +10,7 @@ export const GENE_SEARCH_FAILURE = 'GENE_SEARCH_FAILURE'; export const GENE_SEARCH_SUCCESS = 'GENE_SEARCH_SUCCESS'; export const GENE_SEARCH_RESET = 'GENE_SEARCH_RESET'; export const GENE_SEARCH_CHANGE_FILTER = 'GENE_SEARCH_CHANGE_FILTER'; +export const PASS1AC06_ANALYSIS_CATEGORY_OPTION_CHANGE = 'PASS1AC06_ANALYSIS_CATEGORY_OPTION_CHANGE'; function toggleWeightPlot(weightPlot) { return { @@ -84,6 +85,14 @@ function geneSearchChangeFilter(field, filterValue) { }; } +function pass1ac06AnalysisCategoryOptionChange(category, option) { + return { + type: PASS1AC06_ANALYSIS_CATEGORY_OPTION_CHANGE, + category, + option, + }; +} + const accessToken = process.env.NODE_ENV !== 'production' ? process.env.REACT_APP_ES_ACCESS_TOKEN_DEV @@ -135,6 +144,7 @@ const AnalysisActions = { handleGeneCentricSearch, geneSearchReset, geneSearchChangeFilter, + pass1ac06AnalysisCategoryOptionChange, }; export default AnalysisActions; diff --git a/src/AnalysisPage/analysisReducer.js b/src/AnalysisPage/analysisReducer.js index edf492f3..87ef40a4 100644 --- a/src/AnalysisPage/analysisReducer.js +++ b/src/AnalysisPage/analysisReducer.js @@ -9,6 +9,7 @@ import { GENE_SEARCH_SUCCESS, GENE_SEARCH_RESET, GENE_SEARCH_CHANGE_FILTER, + PASS1AC06_ANALYSIS_CATEGORY_OPTION_CHANGE, } from './analysisActions'; export const defaultGeneSearchParams = { @@ -60,6 +61,16 @@ export const defaultAnalysisState = { geneSearchError: '', scope: 'all', hasResultFilters: {}, + pass1ac06AnalysisCategoryOptions: { + summaryStatistics: { + weight_distribution: true, + lactate_change: true, + rat_work: true, + }, + correlationAnalysis: { + overall_correlation_matrix: true, + }, + }, }; export default function AnalysisReducer( @@ -221,6 +232,17 @@ export default function AnalysisReducer( geneSearchParams: params, }; } + // Handle analysis category option change + case PASS1AC06_ANALYSIS_CATEGORY_OPTION_CHANGE: { + const { category, option } = action; + const newOptions = { ...state.pass1ac06AnalysisCategoryOptions }; + newOptions[category][option] = !newOptions[category][option]; + + return { + ...state, + pass1ac06AnalysisCategoryOptions: newOptions, + }; + } default: return state; } From ca4520ab47218751202aef53884dbe89a04e608f Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 00:04:12 -0800 Subject: [PATCH 12/27] Adjust plot width and remove unused implementation of states --- .../SummaryStatistics/plotWeightDistribution.jsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx index e01575a5..a3761de0 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.jsx @@ -1,5 +1,4 @@ import React, { useMemo } from 'react'; -import { useSelector } from 'react-redux'; import { COLORS, defaultChartOptions, @@ -14,9 +13,6 @@ import Chart from '../chartWrapper'; * @returns JSX representation of Highcharts plots for rat work - boxplots and scatter plots */ function PlotWeightDistribution() { - const analysisState = useSelector((state) => state.analysis); - const { intervention, phase, sex } = analysisState.pass1ac06PlotDisplayOptions; - // Base chart options const baseChartOptions = defaultChartOptions('Intervention', 'Weight', 'Weight: {point.y} grams'); @@ -27,15 +23,6 @@ function PlotWeightDistribution() { // Scatter plot data for pass1a and pass1c (both male and female) const scatterData = useMemo(() => allScatterPlotDataByPhaseSex(getWeightData), []); - // conditionally render x-axis categories based on intervention - const xAxisCategories = () => { - const { acute, control } = intervention; - const categories = []; - if (acute) categories.push('Acute'); - if (control) categories.push('Control'); - return categories.length ? categories : ['Acute', 'Control']; - }; - // Highcharts options for the plots const chartOptions = useMemo(() => { const createChartOptions = (gender, titleText) => { @@ -116,7 +103,7 @@ function PlotWeightDistribution() { }, [baseChartOptions, boxPlotData, scatterData.pass1a, scatterData.pass1c]); return ( -
+
From 0e62094690a0571fe0d55c485ec69216ba5de0c3 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 00:04:54 -0800 Subject: [PATCH 13/27] Adjust plot width --- .../Pass1ac-06/SummaryStatistics/plotLactateChange.jsx | 2 +- .../Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx index 1d01e65d..4085aa57 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotLactateChange.jsx @@ -103,7 +103,7 @@ function PlotLactateChange() { }, [baseChartOptions, boxPlotData, scatterData]); return ( -
+
diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx index 8f135a9c..d840cd2d 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotRatWork.jsx @@ -107,7 +107,7 @@ function PlotRatWork() { }, [baseChartOptions, boxPlotData, scatterData]); return ( -
+
From 7669124129dfe86e6577a40af86f186bf28baccb Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 00:25:14 -0800 Subject: [PATCH 14/27] Add category section content component for overall correlation matrix plots --- .../SummaryStatistics/categorySummaryStatistics.jsx | 2 +- src/AnalysisPage/Phenotype/pass1a06Rats.jsx | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx index a2b952e2..e6845719 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics.jsx @@ -15,7 +15,7 @@ function CategorySummaryStatistics() { const analysisState = useSelector((state) => state.analysis); return ( -
+

Summary Statistics

In this section, various summary statistics and visualizations that diff --git a/src/AnalysisPage/Phenotype/pass1a06Rats.jsx b/src/AnalysisPage/Phenotype/pass1a06Rats.jsx index 3b6b55bb..ed0787b8 100644 --- a/src/AnalysisPage/Phenotype/pass1a06Rats.jsx +++ b/src/AnalysisPage/Phenotype/pass1a06Rats.jsx @@ -1,7 +1,7 @@ import React from 'react'; import AnalysisCategoryNavigation from './Components/Pass1ac-06/analysisCategoryNavigation'; import CategorySummaryStatistics from './Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics'; -import pass1ac06Data from './pass1ac-animal_pheno.json'; +import CategoryCorrelationAnalyses from './Components/Pass1ac-06/correlationAnalyses/categoryCorrelationAnalyses'; /** * Functional component for PASS1AC-06 phenotypic data analysis visualization @@ -24,7 +24,10 @@ function PhenotypePass1a06Rats() { {/* analysis category navigation component */} {/* content of analysis categories */} - +

+ + +
); From d979bd827faaa9987607bc04f209b3ccc282ee7d Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 00:27:44 -0800 Subject: [PATCH 15/27] Initial commit of correlation analyses plot wrapper components --- .../categoryCorrelationAnalyses.jsx | 36 +++++++++++++++++++ .../sectionOverallCorrelationMatrix.jsx | 24 +++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/categoryCorrelationAnalyses.jsx create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/sectionOverallCorrelationMatrix.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/categoryCorrelationAnalyses.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/categoryCorrelationAnalyses.jsx new file mode 100644 index 00000000..95f64fd7 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/categoryCorrelationAnalyses.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { useSelector } from 'react-redux'; +import SectionOverallCorrelationMatrix from './sectionOverallCorrelationMatrix'; + +/** + * 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 CategoryCorrelationAnalyses() { + const analysisState = useSelector((state) => state.analysis); + + return ( +
+

Correlation Analyses

+

+ In this section, we explore the relationships between key variables within + the rat phenotypic data using correlation analyses. By examining how variables + such as weight, distance, lactate change, and electric shocks are related to + each other, we aim to identify patterns and potential dependencies. This helps + to better understand the associations between these variables, which can inform + further analysis of biological significance. The analyses include overall + correlation matrices and detailed pairwise comparisons visualized through + scatter plots and heatmaps. +

+ {/* weight distribution section */} + {analysisState.pass1ac06AnalysisCategoryOptions.correlationAnalysis.overall_correlation_matrix && ( + + )} +
+ ); +} + +export default CategoryCorrelationAnalyses; diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/sectionOverallCorrelationMatrix.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/sectionOverallCorrelationMatrix.jsx new file mode 100644 index 00000000..44da6648 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/sectionOverallCorrelationMatrix.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import PlotOverallCorrelationMatrix from './plotOverallCorrelationMatrix'; + +/** + * Function component for weight distribution section of summary statistics category + * in the PASS1AC-06 phenotypic data analysis + * + * @param {array} phenoData Curated phenotypic data + * + * @returns JSX element of the weight distribution section + */ +function SectionOverallCorrelationMatrix() { + return ( +
+

Overall Correlation Matrix

+
+ {/* phenotpypic data analysis plots */} + +
+
+ ); +} + +export default SectionOverallCorrelationMatrix; From 15b30ecef56e7323ef2af6a9e871c0f96887ff74 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 00:46:51 -0800 Subject: [PATCH 16/27] Remove implementation for groupi plots --- .../Components/Pass1ac-06/sharedLib.js | 58 ------------------- 1 file changed, 58 deletions(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js index 723d415a..60877eb7 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js @@ -12,64 +12,6 @@ export const pass1aFemaleControl = pass1ac06Data.filter((item) => item.phase === export const pass1cFemaleAcute = pass1ac06Data.filter((item) => item.phase === 'pass1c' && item.sex === 'female' && item.intervention === 'acute'); export const pass1cFemaleControl = pass1ac06Data.filter((item) => item.phase === 'pass1c' && item.sex === 'female' && item.intervention === 'control'); -export const groupiCategory = [ - 'acute_00.0h_IPE', 'acute_00.5h', 'acute_01.0h', 'acute_04.0h', - 'acute_07.0h', 'acute_24.0h', 'acute_48.0h', 'control_00.0h', - 'control_00.0h_IPE', 'control_00.5h', 'control_04.0h', 'control_07.0h', -]; - -const createGroupiData = (phase, sex) => groupiCategory.reduce((acc, groupi) => { - acc[groupi] = pass1ac06Data.filter((item) => item.phase === phase && item.sex === sex && item.groupi === groupi); - return acc; -}, {}); - -// male groupi data -export const pass1aMaleGroupi = createGroupiData('pass1a', 'male'); -export const pass1cMaleGroupi = createGroupiData('pass1c', 'male'); - -// female groupi data -export const pass1aFemaleGroupi = createGroupiData('pass1a', 'female'); -export const pass1cFemaleGroupi = createGroupiData('pass1c', 'female'); - -// Function to get all box plot data by phase, sex, and each of the groupi categories -export function allBoxPlotDataByPhaseSexGroupi(processData) { - const boxPlotData = {}; - // male groupi data - Object.keys(pass1aMaleGroupi).forEach((groupi) => { - boxPlotData[`pass1aMale${groupi}`] = calculateBoxPlotData(pass1aMaleGroupi[groupi], processData); - }); - Object.keys(pass1cMaleGroupi).forEach((groupi) => { - boxPlotData[`pass1cMale${groupi}`] = calculateBoxPlotData(pass1cMaleGroupi[groupi], processData); - }); - // female groupi data - Object.keys(pass1aFemaleGroupi).forEach((groupi) => { - boxPlotData[`pass1aFemale${groupi}`] = calculateBoxPlotData(pass1aFemaleGroupi[groupi], processData); - }); - Object.keys(pass1cFemaleGroupi).forEach((groupi) => { - boxPlotData[`pass1cFemale${groupi}`] = calculateBoxPlotData(pass1cFemaleGroupi[groupi], processData); - }); - return boxPlotData; -} - -// Function to get all scatter plot data by phase, sex, and each of the groupi categories -export function allScatterPlotDataByPhaseSexGroupi(processData) { - const getScatterPlots = (groupiData, offset) => Object.keys(groupiData).reduce((acc, groupi) => { - acc[groupi] = processData(groupiData[groupi]).map((value, x) => [x + offset, Math.round(value * 1000) / 1000]); - return acc; - }, {}); - - return { - pass1a: { - male: getScatterPlots(pass1aMaleGroupi, -0.15), - female: getScatterPlots(pass1aFemaleGroupi, -0.15), - }, - pass1c: { - male: getScatterPlots(pass1cMaleGroupi, 0.15), - female: getScatterPlots(pass1cFemaleGroupi, 0.15), - }, - }; -} - // Function to calculate box plot data function calculateBoxPlotData(rawData, processData) { const boxPlotData = processData(rawData).sort((a, b) => a - b); From 644ececea099382fc1c83c4ca649f08adccb3d07 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 11:55:46 -0800 Subject: [PATCH 17/27] Import Highcharts heatmap module --- .../Phenotype/Components/Pass1ac-06/chartWrapper.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx index a7a104e8..4157cfcb 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx @@ -5,6 +5,7 @@ import HighchartsReact from 'highcharts-react-official'; // Import order is important! require('highcharts/highcharts-more')(Highcharts); +require('highcharts/modules/heatmap')(Highcharts); require('highcharts/modules/boost')(Highcharts); require('highcharts/modules/exporting')(Highcharts); require('highcharts/modules/export-data')(Highcharts); From 6c52435a2de127af161fcf90a1280f72ff41357d Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 11:57:13 -0800 Subject: [PATCH 18/27] Add handling to disable checkbox if it's the only unchecked checkbox --- .../Pass1ac-06/analysisCategoryNavigation.jsx | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx index 1d60dcf3..63fb430a 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx @@ -40,28 +40,34 @@ function AnalysisCategoryNavigation() {
{category.title}
- {category.selections.map((sel) => ( -
- dispatch( - AnalysisActions.pass1ac06AnalysisCategoryOptionChange( - category.categoryVal, - sel.value, - ), - )} - /> - -
- ))} + {category.selections.map((sel) => { + const otherValues = category.selections.filter((s) => s.value !== sel.value); + const isOtherChecked = otherValues.find((s) => analysisState.pass1ac06AnalysisCategoryOptions[category.categoryVal][s.value]); + + return ( +
+ dispatch( + AnalysisActions.pass1ac06AnalysisCategoryOptionChange( + category.categoryVal, + sel.value, + ), + )} + /> + +
+ ); +})}
))} From 13d3c023a6573b3b8b3ad3af626cf8cf125bc0eb Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 11:58:40 -0800 Subject: [PATCH 19/27] Add base correlation matrix chart options --- .../Components/Pass1ac-06/sharedLib.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js index 60877eb7..15075e21 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js @@ -115,3 +115,46 @@ export function defaultChartOptions(xAxisTitle, yAxisTitle, scatterTooltipFormat exporting: { enabled: true }, }; } + +// correlation matrix chart options +export function correlationMatrixChartOptions(xAxisTitle, yAxisTitle, tooltipFormat) { + return { + chart: { + type: 'heatmap', + marginTop: 40, + marginBottom: 80, + plotBorderWidth: 1, + }, + xAxis: { + title: { + text: xAxisTitle, + margin: 10, + style: { fontSize: '1.0rem', fontWeight: 'bold' }, + }, + labels: { style: { fontSize: '0.85rem', fontWeight: 'bold' } }, + }, + yAxis: { + title: { + text: yAxisTitle, + margin: 20, + style: { fontSize: '1.0rem', fontWeight: 'bold' }, + }, + labels: { style: { fontSize: '0.85rem', fontWeight: 'bold' } }, + }, + tooltip: { + format: tooltipFormat, + }, + credits: { enabled: false }, + legend: { + layout: 'vertical', + align: 'right', + verticalAlign: 'middle', + padding: 15, + title: { + text: 'Correlation', + style: { fontWeight: 'normal', fontSize: '1.0rem' }, + }, + }, + exporting: { enabled: true }, + }; +} From c1230cbb703d61ad32e5d02ea6186e0a02e78c69 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 11:59:53 -0800 Subject: [PATCH 20/27] Initial commit of plot component for overall correlation matrix in pass1a-06 pheno data analysis --- .../plotOverallCorrelationMatrix.jsx | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx new file mode 100644 index 00000000..805841ca --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx @@ -0,0 +1,147 @@ +import React, { useMemo, useState, useEffect } from 'react'; +import * as ss from 'simple-statistics'; +import { + correlationMatrixChartOptions, +} from '../sharedLib'; +import Chart from '../chartWrapper'; + +const pass1ac06Data = require('../../../pass1ac-animal_pheno.json'); + +/** + * Renders summary statistics plots for weight disctribution + * + * @returns JSX representation of Highcharts plots for rat work - boxplots and scatter plots + */ +function PlotOverallCorrelationMatrix() { + const [corrMatrixData, setCorrMatrixData] = useState(null); + // Filter out the 'control' interventions + const maleAcuteData = pass1ac06Data.filter((item) => item.intervention !== 'control' && item.sex === 'male'); + const femaleAcuteData = pass1ac06Data.filter((item) => item.intervention !== 'control' && item.sex === 'female'); + + // Overall Correlation Matrix chart options + function correlationData() { + const processData = (data) => { + return data.map((item) => { + const { intervention, sex, pid, phase, groupi, ...rest } = item; + const sortedKeys = Object.keys(rest).sort(); + const sortedItem = {}; + sortedKeys.forEach((key) => { + sortedItem[key] = parseFloat(rest[key]); + }); + return sortedItem; + }); + }; + + return { + male: processData(maleAcuteData), + female: processData(femaleAcuteData), + }; + } + + useEffect(() => { + setCorrMatrixData(correlationData()); + }, []); + + // Base chart options + const baseChartOptions = correlationMatrixChartOptions('Variables', 'Variables', '{series.xAxis.categories.(point.x)} vs {series.yAxis.categories.(point.y)}: {point.value}'); + const filteredData = correlationData(); + + // Function to produce correlation matrix data + const generateCorrelationMatrix = (data) => { + const variables = ['distance', 'lactate_change', 'shock_count', 'shock_duration', 'weight', 'work']; + const matrix = []; + + const numSamples = data.length; + + for (let i = 0; i < variables.length; i++) { + for (let j = 0; j < variables.length; j++) { + let correlation = 0; + + // Ensure there are enough data points and non-empty comparisons + if (numSamples > 1) { + const x = data.map((row) => parseFloat(row[variables[i]])); + const y = data.map((row) => parseFloat(row[variables[j]])); + + if (x.some(isNaN) || y.some(isNaN)) { + correlation = 0; + } else { + correlation = ss.sampleCorrelation(x, y) || 0; // Handle NaN cases + } + } + // round correlation vlaue to 2 decimal places + correlation = Math.round(correlation * 100) / 100; + matrix.push([i, j, correlation]); + } + } + + return { matrix, variables }; + }; + + // Highcharts options for the plots + const chartOptions = useMemo(() => { + const createChartOptions = (gender, titleText) => { + const correlationMatrixData = generateCorrelationMatrix(filteredData[gender]); + const { matrix, variables } = correlationMatrixData; + + return { + ...baseChartOptions, + title: { + align: 'left', + style: { fontSize: '1.5rem' }, + text: titleText, + }, + xAxis: { + ...baseChartOptions.xAxis, + categories: variables, + }, + yAxis: { + ...baseChartOptions.yAxis, + categories: variables, + }, + colorAxis: { + min: -1.0, + max: 1.0, + layout: 'vertical', + tickInterval: 0.5, + reversed: false, + stops: [ + [0, '#1532f5'], // Correlation of -1 (bottom) + [0.5, '#ffffff'], // No correlation (middle) + [1, '#ea4025'], // Correlation of 1 (top) + ], + width: 25, + labels: { + format: '{value:.1f}', + }, + }, + series: [ + { + name: 'Correlation by key variables', + borderWidth: 0.5, + borderColor: '#ffffff', + data: matrix, + dataLabels: { + enabled: true, + color: '#000000', + style: { fontSize: 9 }, + }, + }, + ], + }; + }; + + return { + male: createChartOptions('male', 'Correlation Matrix Heatmap (male-acute)'), + female: createChartOptions('female', 'Correlation Matrix Heatmap (female-acute)'), + }; + }, [baseChartOptions, corrMatrixData]); + + return ( +
+ + +
+ ); +} + +export default PlotOverallCorrelationMatrix; From 0dfbb80c3a7e73724cb6a5a8a1c5d0fd1539866d Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 12:00:11 -0800 Subject: [PATCH 21/27] Install dependencies --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index f0e11d87..50c314c6 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "dayjs": "1.11.7", "from-exponential": "^1.1.1", "ga-gtag": "1.2.0", + "highcharts": "^11.4.8", + "highcharts-react-official": "^3.2.1", "history": "4.10.1", "http-proxy-middleware": "^2.0.1", "jquery": "^3.5.1", @@ -34,6 +36,7 @@ "react-tooltip": "^5.11.2", "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" From d4e08dc97731a2695ba309c4e93b858b3cbb8305 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 12:44:49 -0800 Subject: [PATCH 22/27] Initial commit of mocked pass1a-06 pheno data --- .../Phenotype/pass1ac-animal_pheno.json | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/AnalysisPage/Phenotype/pass1ac-animal_pheno.json diff --git a/src/AnalysisPage/Phenotype/pass1ac-animal_pheno.json b/src/AnalysisPage/Phenotype/pass1ac-animal_pheno.json new file mode 100644 index 00000000..f11e91c2 --- /dev/null +++ b/src/AnalysisPage/Phenotype/pass1ac-animal_pheno.json @@ -0,0 +1,28 @@ +[ + { + "pid": "pid_10000000", + "sex": "male", + "intervention": "acute", + "groupi": "acute_01.0h", + "phase": "pass1a", + "weight": "366", + "shock_count": "10", + "shock_duration": "10", + "distance": "408", + "work": "120", + "lactate_change": "6" + }, + { + "pid": "pid_10000001", + "sex": "female", + "intervention": "acute", + "groupi": "acute_00.0h_IPE", + "phase": "pass1a", + "weight": "364", + "shock_count": "20", + "shock_duration": "20", + "distance": "384", + "work": "110", + "lactate_change": "8" + } +] \ No newline at end of file From f797981f8063aee30746467fedf6b16077e1abdf Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 12:58:11 -0800 Subject: [PATCH 23/27] Add dependency --- yarn.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarn.lock b/yarn.lock index 60d9d735..9eaa200e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10461,6 +10461,11 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-statistics@^7.8.7: + version "7.8.7" + resolved "https://registry.yarnpkg.com/simple-statistics/-/simple-statistics-7.8.7.tgz#14b30bfda7ac252da83899362a3cf96a13264c8d" + integrity sha512-ed5FwTNYvkMTfbCai1U+r3symP+lIPKWCqKdudpN4NFNMn9RtDlFtSyAQhCp4oPH0YBjWu/qnW+5q5ZkPB3uHQ== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" From 50c1ccda4d3a7192f59f789378a37ad5973dfdd6 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 13:32:27 -0800 Subject: [PATCH 24/27] Update src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx Fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx index 656694a4..6d44922b 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionRatWork.jsx @@ -31,7 +31,7 @@ function SectionRatWork() {

- {/* phenotpypic data analysis plots */} + {/* phenotypic data analysis plots */}
From 22332993b330bc0e11a67c380d85c430123e3dcf Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 13:32:40 -0800 Subject: [PATCH 25/27] Update src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx Fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx index 6f5bd4a8..405aa11a 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/sectionLactateChange.jsx @@ -14,7 +14,7 @@ function SectionLactateChange() {

Lactate Change (before / after) Due to Acute Exercise

- {/* phenotpypic data analysis plots */} + {/* phenotypic data analysis plots */}
From 6227711559579647e43ecc5ff12117f74f265e2e Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 14:31:09 -0800 Subject: [PATCH 26/27] Enlarge data label text and remove their outline --- .../correlationAnalyses/plotOverallCorrelationMatrix.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx index 805841ca..fdeb11cf 100644 --- a/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx @@ -123,7 +123,7 @@ function PlotOverallCorrelationMatrix() { dataLabels: { enabled: true, color: '#000000', - style: { fontSize: 9 }, + style: { fontSize: '1.25rem', textOutline: 'none' }, }, }, ], From 036acf16ccc3487e635a95aa6171d21920aa93e7 Mon Sep 17 00:00:00 2001 From: Jimmy Zhen Date: Thu, 19 Dec 2024 14:54:16 -0800 Subject: [PATCH 27/27] Add release note info --- src/MultiOmicsWorkingGroups/dawgPAC.jsx | 69 +++++++++++++++++++++++++ src/sass/_multiOmicsWorkingGroups.scss | 2 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/MultiOmicsWorkingGroups/dawgPAC.jsx b/src/MultiOmicsWorkingGroups/dawgPAC.jsx index 854d3ccd..6bec74df 100644 --- a/src/MultiOmicsWorkingGroups/dawgPAC.jsx +++ b/src/MultiOmicsWorkingGroups/dawgPAC.jsx @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import HtmlReportModal from './htmlReportModal'; +import IconSet from '../lib/iconSet'; const proteomicsReportsDA = [ 't55-gastrocnemius_prot-ph_DEA_report.html', @@ -70,6 +71,74 @@ function DawgPAC({ profile }) {

DAWG-PAC: Data Analysis Working Group - PASS1A/1C

+
MoTrPAC Data Freeze: rat-acute-06
+
+ + + + + + + + + + + + + + + +
Data and MetadataCodeMethods
+ Data and Metadata +

+ GCP bucket: +
+ + gs://mawg-data/rat-acute-06 + +

+
+ Code +

+ + Analysis collaboration repository: + +
+ + https://github.com/MoTrPAC/motrpac-rat-acute-6m + +

+
+ Methods +

+ + MoTrPAC MAWG Teamdrive > PASS1A-1C-06 > Writing Methods + +

+
+
+
+ 2024DEC20 Soft Release →{' '} + + Read Notes + +
PASS1A/1C: Acute exercise on young adult rats

The goal of the acute exercise study on young adult rats (designated as diff --git a/src/sass/_multiOmicsWorkingGroups.scss b/src/sass/_multiOmicsWorkingGroups.scss index 4f1da2c4..1a681336 100644 --- a/src/sass/_multiOmicsWorkingGroups.scss +++ b/src/sass/_multiOmicsWorkingGroups.scss @@ -1,6 +1,6 @@ .multiOmicsWorkingGroupsPage { .multi-omics-wg-tab-content { - .pre-cawg { + .pre-cawg, .dawg-pac { .resources-table { th { text-align: center;