diff --git a/package.json b/package.json index 7246dd9a..9c84833b 100644 --- a/package.json +++ b/package.json @@ -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" 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..e6845719 --- /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; 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..4085aa57 --- /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..d840cd2d --- /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..a3761de0 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/SummaryStatistics/plotWeightDistribution.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 weight disctribution + * + * @returns JSX representation of Highcharts plots for rat work - boxplots and scatter plots + */ +function PlotWeightDistribution() { + // 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), []); + + // 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; 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..405aa11a --- /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

+
+ {/* phenotypic 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..6d44922b --- /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 + +

+
+ {/* phenotypic 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; 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..63fb430a --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/analysisCategoryNavigation.jsx @@ -0,0 +1,80 @@ +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) => { + 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, + ), + )} + /> + +
+ ); +})} +
+
+ ))} +
+
+
+ ); +} + +export default AnalysisCategoryNavigation; 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..4157cfcb --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/chartWrapper.jsx @@ -0,0 +1,42 @@ +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/heatmap')(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; 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/plotOverallCorrelationMatrix.jsx b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/correlationAnalyses/plotOverallCorrelationMatrix.jsx new file mode 100644 index 00000000..fdeb11cf --- /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: '1.25rem', textOutline: 'none' }, + }, + }, + ], + }; + }; + + return { + male: createChartOptions('male', 'Correlation Matrix Heatmap (male-acute)'), + female: createChartOptions('female', 'Correlation Matrix Heatmap (female-acute)'), + }; + }, [baseChartOptions, corrMatrixData]); + + return ( +
+ + +
+ ); +} + +export default PlotOverallCorrelationMatrix; 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; 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..15075e21 --- /dev/null +++ b/src/AnalysisPage/Phenotype/Components/Pass1ac-06/sharedLib.js @@ -0,0 +1,160 @@ +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'); + +// 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 }, + }; +} + +// 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 }, + }; +} diff --git a/src/AnalysisPage/Phenotype/pass1a06Rats.jsx b/src/AnalysisPage/Phenotype/pass1a06Rats.jsx new file mode 100644 index 00000000..ed0787b8 --- /dev/null +++ b/src/AnalysisPage/Phenotype/pass1a06Rats.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import AnalysisCategoryNavigation from './Components/Pass1ac-06/analysisCategoryNavigation'; +import CategorySummaryStatistics from './Components/Pass1ac-06/SummaryStatistics/categorySummaryStatistics'; +import CategoryCorrelationAnalyses from './Components/Pass1ac-06/correlationAnalyses/categoryCorrelationAnalyses'; + +/** + * 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; 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 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); 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; } 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; 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/_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/_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; 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; } } } 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"