Skip to content

Commit a55aec3

Browse files
Merge pull request #67 from AhmedBasem20/dashboard-page
Add algorithm comparison and visualization dashboard
2 parents b099579 + cae60b1 commit a55aec3

File tree

7 files changed

+775
-4
lines changed

7 files changed

+775
-4
lines changed

.github/workflows/documentation.yml renamed to .github/workflows/website.yml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build & Deploy Documentation
1+
name: Build & Deploy Website
22

33
on:
44
workflow_run:
@@ -33,25 +33,39 @@ jobs:
3333
run: |
3434
pip install -r requirements.txt
3535
36-
# Action to download artifacts from a different workflow (analysis.yml)
36+
# Action Figures artifact
3737
- name: 'Download artifact'
3838
if: ${{ github.event.workflow_run.conclusion == 'success' }}
3939
uses: ./.github/actions/download-artifact
4040
with:
4141
name: 'Figures'
42+
# Action analysis data artifact
43+
- name: 'Download analysis data'
44+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
45+
uses: ./.github/actions/download-artifact
46+
with:
47+
name: 'Data'
4248

43-
- name: Build html
49+
- name: move data to the dashboard folder
50+
run: |
51+
mv test_output.csv website/dashboard
52+
53+
- name: Build documentation
4454
run: |
4555
mkdir docs/_static
4656
mv *.pdf docs/_static/
4757
sphinx-apidoc -o docs src
4858
cd docs/
4959
make html
5060
61+
- name: move data to the website folder
62+
run: |
63+
mv "docs/_build/html" "website/documentation"
64+
5165
- name: Upload docs artifact
5266
uses: actions/upload-pages-artifact@v3
5367
with:
54-
path: 'docs/_build/html'
68+
path: 'website'
5569

5670
deploy:
5771
needs: build
File renamed without changes.

website/dashboard/index.css

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
:root {
2+
--primary-color: #072A6A;
3+
--accent-color: #62D58A;
4+
--primary-white: #fff;
5+
--background-color: #f4f4f9;
6+
--shadow: rgba(0, 0, 0, 0.2);
7+
}
8+
9+
body {
10+
margin: 0;
11+
padding: 0;
12+
font-family: 'Inter', 'Atkinson Hyperlegible', sans-serif;
13+
background-color: var(--background-color);
14+
}
15+
16+
header {
17+
padding: 1rem 2rem;
18+
background-color: var(--primary-color);
19+
color: var(--primary-white);
20+
}
21+
22+
.bar-title {
23+
margin: 0;
24+
font-size: 2rem;
25+
font-weight: 600;
26+
}
27+
28+
.divider {
29+
margin: 0.5rem 0;
30+
border: none;
31+
border-top: 2px solid var(--accent-color);
32+
}
33+
34+
main {
35+
padding: 2rem;
36+
}
37+
38+
.filter-wrapper {
39+
margin: 2rem;
40+
font-size: x-large;
41+
font-weight: bold;
42+
}
43+
44+
.filter-menu {
45+
padding: 0.5rem 1rem;
46+
border: none;
47+
border-radius: 5px;
48+
background-color: var(--primary-color);
49+
color: var(--primary-white);
50+
font-size: 1rem;
51+
cursor: pointer;
52+
transition: background-color 0.3s ease, color 0.3s ease;
53+
}
54+
55+
.filter-menu:hover {
56+
background-color: var(--accent-color);
57+
}
58+
59+
.chart-card {
60+
padding: 2rem;
61+
border-radius: 1rem;
62+
box-shadow: 0px 8px 16px var(--shadow);
63+
background-color: var(--primary-white);
64+
transition: transform 0.3s ease, box-shadow 0.3s ease;
65+
}
66+
67+
.chart-card:hover {
68+
transform: translateY(-5px);
69+
box-shadow: 0px 12px 24px var(--shadow);
70+
}
71+
72+
.slider-container {
73+
display: flex;
74+
align-items: center;
75+
margin: 20px 0;
76+
width: 30%;
77+
}
78+
.slider-label {
79+
margin-right: 10px;
80+
font-weight: bold;
81+
color: #333;
82+
}
83+
.slider {
84+
margin: 0 10px;
85+
flex-grow: 1;
86+
height: 16px;
87+
background: #ddd;
88+
outline: none;
89+
opacity: 0.9;
90+
transition: opacity 1.2s;
91+
}
92+
.slider:hover {
93+
opacity: 1;
94+
height: 25px;
95+
cursor: pointer;
96+
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
97+
}
98+
99+
.slider-value {
100+
margin: 0 10px;
101+
font-weight: bold;
102+
color: #333;
103+
}
104+
105+
.spinner {
106+
border: 8px solid rgba(0, 0, 0, 0.1);
107+
width: 76px;
108+
height: 76px;
109+
border-radius: 50%;
110+
border-top-color: #3498db;
111+
animation: spin 1s ease-in-out infinite;
112+
}
113+
114+
@keyframes spin {
115+
to { transform: rotate(360deg); }
116+
}
117+
118+
.loading-overlay {
119+
position: fixed;
120+
top: 0;
121+
left: 0;
122+
right: 0;
123+
bottom: 0;
124+
display: flex;
125+
align-items: center;
126+
justify-content: center;
127+
}
128+
129+
.hidden {
130+
display: none;
131+
}

website/dashboard/index.html

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>IVIM MRI Algorithm Fitting Dashboard</title>
7+
<!-- Load Plotly.js into the DOM -->
8+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
9+
<script src="https://cdn.plot.ly/plotly-2.30.0.min.js"></script>
10+
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.0/papaparse.min.js"></script>
11+
<script src="index.js"></script>
12+
<link rel="stylesheet" href="index.css">
13+
</head>
14+
<body>
15+
<div id="root">
16+
<div class="loading-overlay hidden" id="loadingOverlay">
17+
<div class="spinner"></div>
18+
</div>
19+
<header>
20+
<h1 class="bar-title">IVIM MRI Algorithm Fitting Dashboard</h1>
21+
<hr class="divider" />
22+
</header>
23+
<main>
24+
<div class="filter-wrapper">
25+
<label for="algorithm-select">Algorithm:</label>
26+
<select id="algorithm-select" class="filter-menu">
27+
<!-- Options will be populated dynamically -->
28+
</select>
29+
30+
<label for="snr-select">SNR:</label>
31+
<select id="snr-select" class="filter-menu">
32+
<!-- Options will be populated dynamically -->
33+
</select>
34+
35+
<label for="type-select">Type: </label>
36+
<select id="type-select" class="filter-menu">
37+
<option value="D_fitted">Diffusion</option>
38+
<option value="Dp_fitted">Perfusion</option>
39+
<option value="f_fitted">Perfusion Fraction</option>
40+
</select>
41+
42+
<div class="slider-container">
43+
<span class="slider-label">Upper Range:</span>
44+
<button id="decrement-range" class="slider-button">-</button>
45+
<input type="range" id="range-slider" class="slider" min="2" max="100" step="1" value="2">
46+
<button id="increment-range" class="slider-button">+</button>
47+
<span id="range-value" class="slider-value">2</span>
48+
</div>
49+
<div id="lower-slider" class="slider-container">
50+
<span class="slider-label">Lower Range:</span>
51+
<button id="decrement-lower-range" class="slider-button">+</button>
52+
<input type="range" id="lower-range-slider" class="slider" min="2" max="100" step="2" value="2">
53+
<button id="increment-lower-range" class="slider-button">-</button>
54+
<span id="lower-range-value" class="slider-value">2</span>
55+
</div>
56+
</div>
57+
<div class="chart-card" id="myDiv">
58+
<!-- Chart will be rendered here -->
59+
</div>
60+
61+
62+
<!-- New section for region-based plot -->
63+
<div class="filter-wrapper">
64+
<label for="region-select">Region:</label>
65+
<select id="region-select" class="filter-menu">
66+
<!-- Options will be populated dynamically -->
67+
</select>
68+
69+
<label for="snr-region-select">SNR:</label>
70+
<select id="snr-region-select" class="filter-menu">
71+
<!-- Options will be populated dynamically -->
72+
</select>
73+
74+
<label for="type-region-select">Type: </label>
75+
<select id="type-region-select" class="filter-menu">
76+
<option value="D_fitted">Diffusion</option>
77+
<option value="Dp_fitted">Perfusion</option>
78+
<option value="f_fitted">Perfusion Fraction</option>
79+
</select>
80+
81+
<div class="slider-container">
82+
<span class="slider-label">Upper Range:</span>
83+
<button id="decrement-range-region" class="slider-button">-</button>
84+
<input type="range" id="range-slider-region" class="slider" min="2" max="100" step="2" value="2">
85+
<button id="increment-range-region" class="slider-button">+</button>
86+
<span id="range-value-region" class="slider-value">2</span>
87+
</div>
88+
<div id="region-lower-slider" class="slider-container">
89+
<span class="slider-label">Lower Range:</span>
90+
<button id="decrement-lower-range-region" class="slider-button">+</button>
91+
<input type="range" id="lower-range-slider-region" class="slider" min="2" max="100" step="2" value="2">
92+
<button id="increment-lower-range-region" class="slider-button">-</button>
93+
<span id="lower-range-value-region" class="slider-value">2</span>
94+
</div>
95+
</div>
96+
<div class="chart-card" id="regionDiv">
97+
<!-- New chart will be rendered here -->
98+
</div>
99+
100+
101+
</main>
102+
</div>
103+
</body>
104+
</html>

0 commit comments

Comments
 (0)