-
Notifications
You must be signed in to change notification settings - Fork 0
/
humanGeneMetaAnalysis.jsx
197 lines (180 loc) · 8.04 KB
/
humanGeneMetaAnalysis.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import React, { useState } from 'react';
import HumanMetaAnalysisAcuteMuscleGenes from '../data/humanMetaAnalysisAcuteMuscleGenes';
import PlotFOXO1 from '../assets/plots/analysis/meta-analysis/human/acute-muscle/FOXO1.png';
import PlotID1 from '../assets/plots/analysis/meta-analysis/human/acute-muscle/ID1.png';
import PlotPPARGC1A from '../assets/plots/analysis/meta-analysis/human/acute-muscle/PPARGC1A.png';
import PlotSMAD3 from '../assets/plots/analysis/meta-analysis/human/acute-muscle/SMAD3.png';
import PlotVEGFA from '../assets/plots/analysis/meta-analysis/human/acute-muscle/VEGFA.png';
const plotMapping = {
FOXO1: PlotFOXO1,
ID1: PlotID1,
PPARGC1A: PlotPPARGC1A,
SMAD3: PlotSMAD3,
VEGFA: PlotVEGFA,
};
const humanMetaAnalysisAcuteMuscleGeneStats = require('../data/human_meta_analysis_acute_muscle_gene_stats');
/**
* Functional component to render human meta-analysis acute muscle data visualization
* It uses internal states not shared by other components
*
* @return {Object} JSX representation of the meta analysis data visualization
*/
function HumanGeneMetaAnalysis() {
// Local states
const [inputValue, setInputValue] = useState('');
const [gene, setGene] = useState('');
/**
* Simple Math.round method
* alternative #1 - Math.round(num * 10) / 10; //*** returns 1 decimal
* alternative #2 - Math.round((num + 0.00001) * 100) / 100; //*** returns 2 decimals
*/
const classificationMathRound = (number, decimals) => {
return Number(Math.round(number + ('e' + decimals)) + ('e-' + decimals));
};
const geneObj = humanMetaAnalysisAcuteMuscleGeneStats
.find(item => item.Symbol === gene.toUpperCase());
// Renders found gene stats info in the gene search panel
const renderGeneInfo = () => {
if (geneObj && Object.keys(geneObj).length) {
const geneObjClone = { ...geneObj };
delete geneObjClone.Summary;
return (
<div className="gene-search-result">
<table className="table table-borderless table-striped">
<tbody>
{Object.entries(geneObjClone).map(([key, value]) => {
return (
<tr key={key}>
<th scope="row">{`${key}:`}</th>
<td>{!Number.isNaN(classificationMathRound(Number(value), 2)) ? classificationMathRound(Number(value), 2) : value}</td>
</tr>
);
})}
<tr>
<td colSpan="2">
<div className="font-weight-bold">Summary:</div>
{geneObj.Summary}
</td>
</tr>
</tbody>
</table>
</div>
);
}
return <div className="gene-search-result">No matching gene found.</div>;
};
const geneAanlysisDataArray = HumanMetaAnalysisAcuteMuscleGenes[gene.toUpperCase()]
? HumanMetaAnalysisAcuteMuscleGenes[gene.toUpperCase()] : null;
// Renders table head of gene meta-analysis
const renderMetaAnalysisTableHead = () => {
return (
<tr className="table-head">
<th scope="col" className="gene-meta-analysis-label text-nowrap">Cohort ID</th>
<th scope="col" className="gene-meta-analysis-label text-nowrap">Geo ID</th>
<th scope="col" className="gene-meta-analysis-label text-nowrap">Training</th>
<th scope="col" className="gene-meta-analysis-label text-nowrap">Avg Age</th>
<th scope="col" className="gene-meta-analysis-label text-nowrap">Age SD</th>
<th scope="col" className="gene-meta-analysis-label text-nowrap">SDD</th>
</tr>
);
};
// Renders individual rows of gene meta-analysis data
const renderMetaAnalysisTableRows = (data) => {
const rows = data.map(item => (
<tr key={item.sdd} className={`${item.avg_age} ${item.age_sd} ${item.sdd}`}>
<td className="gene-meta-analysis-value text-nowrap">{item.V1}</td>
<td className="gene-meta-analysis-value text-nowrap">{item.gse}</td>
<td className="gene-meta-analysis-value text-nowrap">{item.training}</td>
<td className="gene-meta-analysis-value text-nowrap">{classificationMathRound(Number(item.avg_age), 2)}</td>
<td className="gene-meta-analysis-value text-nowrap">{classificationMathRound(Number(item.age_sd), 2)}</td>
<td className="gene-meta-analysis-value text-nowrap">{classificationMathRound(Number(item.sdd), 2)}</td>
</tr>
));
return rows;
};
// Renders meta-analysis of a gene for acute muscle
const renderMetaAnalysisData = () => {
if (geneAanlysisDataArray && geneAanlysisDataArray.length) {
return (
<div className="meta-analysis-data-content d-flex align-items-start">
<div className="col meta-analysis-data-gene-acute-muscle">
<div className="table-responsive meta-analysis-data-table-wrapper">
<table className="table table-sm table-striped metaAnalysisAcuteMuscleGeneTable">
<thead className="thead-dark">
{renderMetaAnalysisTableHead()}
</thead>
<tbody>
{renderMetaAnalysisTableRows(geneAanlysisDataArray)}
</tbody>
</table>
</div>
<div className="note-comment d-flex align-items-center text-secondary">
<span className="material-icons">info</span>
<span>A cohort can have more than a single data point in a time window.</span>
</div>
</div>
<div className="col meta-analysis-forest-plot">
<img src={plotMapping[gene.toUpperCase()]} alt={gene.toUpperCase()} />
</div>
</div>
);
}
return null;
};
return (
<div className="human-gene-meta-analysis">
<div className="alert alert-warning alert-dismissible fade show warning-note d-flex align-items-center" role="alert">
<span className="material-icons">info</span>
<span className="warning-note-text">
The following analyses use existing published data sets. They
do not represent the complete meta-analysis data set. Only
5 genes (FOXO1, ID1, PPARGC1A, SMAD3, VEGFA) are available for
searching in this release.
</span>
<button type="button" className="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="d-flex justify-content-center meta-analysis-content-container">
{/* gene search */}
<div className="card gene-search-container col-12 col-md-3">
<div className="card-body">
<h6 className="card-title">Select a gene:</h6>
<div className="gene-search-content">
<form id="metaAnalysisGeneSearchForm" name="metaAnalysisGeneSearchForm">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
value={inputValue}
placeholder="Gene symbol"
aria-label="Gene symbol"
aria-describedby="gene-search-btn"
onChange={(e) => { e.preventDefault(); setInputValue(e.target.value); }}
/>
<div className="input-group-append">
<button
type="button"
id="gene-search-btn"
className="btn btn-primary"
onClick={(e) => { e.preventDefault(); setGene(inputValue); }}
>
<i className="material-icons">search</i>
</button>
</div>
</div>
</form>
</div>
{renderGeneInfo()}
</div>
</div>
{/* meta-analysis acute muscle data */}
<div className="col meta-analysis-data-container">
<h5>{`Meta-Analysis${geneObj && geneObj.Symbol ? ` of ${geneObj.Symbol.toUpperCase()}` : ''} for Acute Muscle`}</h5>
{renderMetaAnalysisData()}
</div>
</div>
</div>
);
}
export default HumanGeneMetaAnalysis;