arihant3704 commited on
Commit
450d83e
·
verified ·
1 Parent(s): 99ad468

ECG Monitoring app.

Requirements:

→ No hardware, it should randomly take numbers for every one second.

2 It should segerate weather the reading is regural (or) inregular.

3) It should show it gives. eeg graphs for the reading

9) It should store history of the readings 5 Amy ather additions gel free to add only in html

Files changed (6) hide show
  1. README.md +7 -4
  2. components/footer.js +33 -0
  3. components/navbar.js +35 -0
  4. index.html +133 -19
  5. script.js +257 -0
  6. style.css +15 -22
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Heartbeats Graphs Visualizer
3
- emoji: 📚
4
- colorFrom: pink
5
  colorTo: yellow
 
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: HeartBeats & Graphs Visualizer 🫀
3
+ colorFrom: yellow
 
4
  colorTo: yellow
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/footer.js ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ footer {
7
+ background-color: #1F2937;
8
+ }
9
+ .footer-link:hover {
10
+ color: #EF4444;
11
+ }
12
+ </style>
13
+ <footer class="text-gray-300 py-8">
14
+ <div class="container mx-auto px-4">
15
+ <div class="flex flex-col md:flex-row justify-between items-center">
16
+ <div class="mb-4 md:mb-0">
17
+ <p class="text-sm">&copy; ${new Date().getFullYear()} HeartBeats Visualizer. Not a real medical device.</p>
18
+ </div>
19
+ <div class="flex space-x-4">
20
+ <a href="#" class="footer-link text-sm">Privacy Policy</a>
21
+ <a href="#" class="footer-link text-sm">Terms of Service</a>
22
+ <a href="#" class="footer-link text-sm">Contact Us</a>
23
+ </div>
24
+ </div>
25
+ <div class="mt-6 text-center text-xs text-gray-500">
26
+ <p>This is a simulation for demonstration purposes only. Not intended for medical use.</p>
27
+ </div>
28
+ </div>
29
+ </footer>
30
+ `;
31
+ }
32
+ }
33
+ customElements.define('custom-footer', CustomFooter);
components/navbar.js ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ .navbar {
7
+ background: linear-gradient(135deg, #EF4444 0%, #991B1B 100%);
8
+ }
9
+ .nav-link:hover {
10
+ background-color: rgba(255, 255, 255, 0.1);
11
+ }
12
+ </style>
13
+ <nav class="navbar text-white shadow-lg">
14
+ <div class="container mx-auto px-4">
15
+ <div class="flex justify-between items-center py-4">
16
+ <div class="flex items-center space-x-2">
17
+ <i data-feather="activity" class="w-8 h-8"></i>
18
+ <span class="text-xl font-bold">HeartBeats Visualizer</span>
19
+ </div>
20
+ <div class="hidden md:flex items-center space-x-1">
21
+ <a href="#" class="nav-link px-3 py-2 rounded-md text-sm font-medium">Dashboard</a>
22
+ <a href="#" class="nav-link px-3 py-2 rounded-md text-sm font-medium">History</a>
23
+ <a href="#" class="nav-link px-3 py-2 rounded-md text-sm font-medium">Settings</a>
24
+ <a href="#" class="nav-link px-3 py-2 rounded-md text-sm font-medium">Help</a>
25
+ </div>
26
+ <button class="md:hidden focus:outline-none">
27
+ <i data-feather="menu" class="w-6 h-6"></i>
28
+ </button>
29
+ </div>
30
+ </div>
31
+ </nav>
32
+ `;
33
+ }
34
+ }
35
+ customElements.define('custom-navbar', CustomNavbar);
index.html CHANGED
@@ -1,19 +1,133 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>HeartBeats Visualizer</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
12
+ </head>
13
+ <body class="bg-gray-100 min-h-screen">
14
+ <custom-navbar></custom-navbar>
15
+
16
+ <main class="container mx-auto px-4 py-8">
17
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
18
+ <!-- Left Column -->
19
+ <div class="lg:col-span-2 space-y-8">
20
+ <!-- Live ECG Graph -->
21
+ <div class="bg-white rounded-xl shadow-lg p-6">
22
+ <div class="flex justify-between items-center mb-6">
23
+ <h2 class="text-2xl font-bold text-gray-800">Live ECG Monitoring</h2>
24
+ <div id="heartStatus" class="flex items-center">
25
+ <span class="h-4 w-4 rounded-full bg-red-500 animate-pulse mr-2"></span>
26
+ <span class="text-gray-600">Analyzing...</span>
27
+ </div>
28
+ </div>
29
+ <div class="h-64">
30
+ <canvas id="ecgChart"></canvas>
31
+ </div>
32
+ <div class="mt-6 flex justify-between items-center">
33
+ <button id="pauseBtn" class="px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition">
34
+ <i data-feather="pause"></i> Pause
35
+ </button>
36
+ <div class="text-sm text-gray-500">
37
+ <span id="bpmDisplay" class="text-lg font-semibold text-gray-800">--</span> BPM
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <!-- History Section -->
43
+ <div class="bg-white rounded-xl shadow-lg p-6">
44
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">Reading History</h2>
45
+ <div class="overflow-x-auto">
46
+ <table class="min-w-full divide-y divide-gray-200">
47
+ <thead class="bg-gray-50">
48
+ <tr>
49
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Time</th>
50
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">BPM</th>
51
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
52
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Details</th>
53
+ </tr>
54
+ </thead>
55
+ <tbody id="historyTable" class="bg-white divide-y divide-gray-200">
56
+ <!-- History rows will be added here by JavaScript -->
57
+ </tbody>
58
+ </table>
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <!-- Right Column -->
64
+ <div class="space-y-8">
65
+ <!-- Heart Rate Stats -->
66
+ <div class="bg-white rounded-xl shadow-lg p-6">
67
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">Current Reading</h2>
68
+ <div class="space-y-4">
69
+ <div class="flex justify-between items-center">
70
+ <span class="text-gray-600">Current BPM</span>
71
+ <span id="currentBpm" class="text-2xl font-bold text-gray-800">--</span>
72
+ </div>
73
+ <div class="flex justify-between items-center">
74
+ <span class="text-gray-600">Average BPM</span>
75
+ <span id="averageBpm" class="text-2xl font-bold text-gray-800">--</span>
76
+ </div>
77
+ <div class="flex justify-between items-center">
78
+ <span class="text-gray-600">Min BPM</span>
79
+ <span id="minBpm" class="text-2xl font-bold text-gray-800">--</span>
80
+ </div>
81
+ <div class="flex justify-between items-center">
82
+ <span class="text-gray-600">Max BPM</span>
83
+ <span id="maxBpm" class="text-2xl font-bold text-gray-800">--</span>
84
+ </div>
85
+ </div>
86
+ </div>
87
+
88
+ <!-- Irregularity Analysis -->
89
+ <div class="bg-white rounded-xl shadow-lg p-6">
90
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">Irregularity Analysis</h2>
91
+ <div id="irregularityStatus" class="text-center py-4 px-6 rounded-lg bg-red-100 text-red-800 mb-4">
92
+ <i data-feather="alert-circle" class="inline mr-2"></i>
93
+ <span>No irregular beats detected</span>
94
+ </div>
95
+ <div class="space-y-3">
96
+ <div class="flex justify-between items-center">
97
+ <span class="text-gray-600">Irregular Beats</span>
98
+ <span id="irregularBeats" class="font-semibold">0</span>
99
+ </div>
100
+ <div class="flex justify-between items-center">
101
+ <span class="text-gray-600">Last Irregularity</span>
102
+ <span id="lastIrregularity" class="font-semibold">--</span>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
+ <!-- Quick Actions -->
108
+ <div class="bg-white rounded-xl shadow-lg p-6">
109
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">Quick Actions</h2>
110
+ <div class="space-y-3">
111
+ <button id="exportBtn" class="w-full px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition flex items-center justify-center">
112
+ <i data-feather="download" class="mr-2"></i> Export Data
113
+ </button>
114
+ <button id="clearBtn" class="w-full px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
115
+ <i data-feather="trash-2" class="mr-2"></i> Clear History
116
+ </button>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </main>
122
+
123
+ <custom-footer></custom-footer>
124
+
125
+ <script src="components/navbar.js"></script>
126
+ <script src="components/footer.js"></script>
127
+ <script src="script.js"></script>
128
+ <script>
129
+ feather.replace();
130
+ </script>
131
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
132
+ </body>
133
+ </html>
script.js ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Global variables
2
+ let ecgData = [];
3
+ let bpmHistory = [];
4
+ let historyRecords = [];
5
+ let isPaused = false;
6
+ let updateInterval;
7
+ let ecgChart;
8
+
9
+ // Initialize the application
10
+ document.addEventListener('DOMContentLoaded', function() {
11
+ initializeChart();
12
+ startMonitoring();
13
+ setupEventListeners();
14
+ });
15
+
16
+ function initializeChart() {
17
+ const ctx = document.getElementById('ecgChart').getContext('2d');
18
+
19
+ ecgChart = new Chart(ctx, {
20
+ type: 'line',
21
+ data: {
22
+ labels: Array(100).fill(''),
23
+ datasets: [{
24
+ label: 'ECG',
25
+ data: Array(100).fill(0),
26
+ borderColor: '#EF4444',
27
+ borderWidth: 2,
28
+ tension: 0.1,
29
+ pointRadius: 0
30
+ }]
31
+ },
32
+ options: {
33
+ responsive: true,
34
+ maintainAspectRatio: false,
35
+ scales: {
36
+ y: {
37
+ min: -2,
38
+ max: 2,
39
+ display: false
40
+ },
41
+ x: {
42
+ display: false
43
+ }
44
+ },
45
+ animation: {
46
+ duration: 0
47
+ },
48
+ plugins: {
49
+ legend: {
50
+ display: false
51
+ }
52
+ }
53
+ }
54
+ });
55
+ }
56
+
57
+ function startMonitoring() {
58
+ // Initial data
59
+ generateInitialData();
60
+
61
+ // Start updating the chart every second
62
+ updateInterval = setInterval(updateECGData, 1000);
63
+ }
64
+
65
+ function generateInitialData() {
66
+ // Generate some initial random ECG-like data
67
+ for (let i = 0; i < 100; i++) {
68
+ ecgData.push(generateECGPoint(i));
69
+ }
70
+ updateChart();
71
+ }
72
+
73
+ function generateECGPoint(index) {
74
+ // Simulate ECG data with some randomness
75
+ const position = index % 100;
76
+
77
+ // Generate a basic ECG waveform with some randomness
78
+ if (position > 90) {
79
+ return 0.2 + Math.random() * 0.1;
80
+ } else if (position > 80) {
81
+ return -0.5 - Math.random() * 0.2;
82
+ } else if (position > 70) {
83
+ return 1.5 + Math.random() * 0.3;
84
+ } else if (position > 60) {
85
+ return -0.8 - Math.random() * 0.2;
86
+ } else if (position > 50) {
87
+ return 0.3 + Math.random() * 0.1;
88
+ } else {
89
+ // Baseline with some small noise
90
+ return (Math.random() - 0.5) * 0.2;
91
+ }
92
+ }
93
+
94
+ function updateECGData() {
95
+ if (isPaused) return;
96
+
97
+ // Remove first point and add new one
98
+ ecgData.shift();
99
+ ecgData.push(generateECGPoint(Math.floor(Math.random() * 100)));
100
+
101
+ // Update chart
102
+ updateChart();
103
+
104
+ // Calculate and display BPM
105
+ const bpm = 60 + Math.floor(Math.random() * 60);
106
+ updateBPM(bpm);
107
+
108
+ // Check for irregularity (10% chance)
109
+ const isIrregular = Math.random() < 0.1;
110
+ updateIrregularityStatus(isIrregular, bpm);
111
+
112
+ // Add to history
113
+ addToHistory(bpm, isIrregular);
114
+
115
+ // Update stats
116
+ updateStats();
117
+ }
118
+
119
+ function updateChart() {
120
+ ecgChart.data.datasets[0].data = ecgData;
121
+ ecgChart.update();
122
+ }
123
+
124
+ function updateBPM(bpm) {
125
+ document.getElementById('bpmDisplay').textContent = bpm;
126
+ document.getElementById('currentBpm').textContent = bpm;
127
+ bpmHistory.push(bpm);
128
+
129
+ // Limit history to last 100 readings
130
+ if (bpmHistory.length > 100) {
131
+ bpmHistory.shift();
132
+ }
133
+ }
134
+
135
+ function updateIrregularityStatus(isIrregular, bpm) {
136
+ const statusElement = document.getElementById('irregularityStatus');
137
+ const heartStatus = document.getElementById('heartStatus');
138
+
139
+ if (isIrregular) {
140
+ statusElement.innerHTML = `
141
+ <i data-feather="alert-circle" class="inline mr-2"></i>
142
+ <span>Irregular heartbeat detected (${bpm} BPM)</span>
143
+ `;
144
+ statusElement.className = 'text-center py-4 px-6 rounded-lg irregular mb-4';
145
+ heartStatus.innerHTML = `
146
+ <span class="h-4 w-4 rounded-full bg-yellow-500 animate-pulse mr-2"></span>
147
+ <span class="text-gray-600">Irregular</span>
148
+ `;
149
+ } else {
150
+ statusElement.innerHTML = `
151
+ <i data-feather="check-circle" class="inline mr-2"></i>
152
+ <span>Regular heartbeat (${bpm} BPM)</span>
153
+ `;
154
+ statusElement.className = 'text-center py-4 px-6 rounded-lg regular mb-4';
155
+ heartStatus.innerHTML = `
156
+ <span class="h-4 w-4 rounded-full bg-green-500 animate-pulse mr-2"></span>
157
+ <span class="text-gray-600">Regular</span>
158
+ `;
159
+ }
160
+ feather.replace();
161
+ }
162
+
163
+ function addToHistory(bpm, isIrregular) {
164
+ const now = new Date();
165
+ const timeString = now.toLocaleTimeString();
166
+
167
+ historyRecords.unshift({
168
+ time: timeString,
169
+ bpm: bpm,
170
+ isIrregular: isIrregular,
171
+ timestamp: now.getTime()
172
+ });
173
+
174
+ // Limit history to 50 records
175
+ if (historyRecords.length > 50) {
176
+ historyRecords.pop();
177
+ }
178
+
179
+ updateHistoryTable();
180
+ }
181
+
182
+ function updateHistoryTable() {
183
+ const tableBody = document.getElementById('historyTable');
184
+ tableBody.innerHTML = '';
185
+
186
+ historyRecords.forEach(record => {
187
+ const row = document.createElement('tr');
188
+
189
+ row.innerHTML = `
190
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${record.time}</td>
191
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium ${record.isIrregular ? 'text-yellow-600' : 'text-gray-900'}">${record.bpm}</td>
192
+ <td class="px-6 py-4 whitespace-nowrap text-sm">
193
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${record.isIrregular ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800'}">
194
+ ${record.isIrregular ? 'Irregular' : 'Regular'}
195
+ </span>
196
+ </td>
197
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
198
+ <button class="text-blue-500 hover:text-blue-700">
199
+ <i data-feather="info" class="w-4 h-4"></i>
200
+ </button>
201
+ </td>
202
+ `;
203
+
204
+ tableBody.appendChild(row);
205
+ });
206
+
207
+ feather.replace();
208
+ }
209
+
210
+ function updateStats() {
211
+ if (bpmHistory.length === 0) return;
212
+
213
+ const sum = bpmHistory.reduce((a, b) => a + b, 0);
214
+ const avg = Math.round(sum / bpmHistory.length);
215
+ const min = Math.min(...bpmHistory);
216
+ const max = Math.max(...bpmHistory);
217
+
218
+ document.getElementById('averageBpm').textContent = avg;
219
+ document.getElementById('minBpm').textContent = min;
220
+ document.getElementById('maxBpm').textContent = max;
221
+
222
+ // Update irregular beats count
223
+ const irregularCount = historyRecords.filter(r => r.isIrregular).length;
224
+ document.getElementById('irregularBeats').textContent = irregularCount;
225
+
226
+ // Update last irregularity time
227
+ const lastIrregular = historyRecords.find(r => r.isIrregular);
228
+ if (lastIrregular) {
229
+ document.getElementById('lastIrregularity').textContent = lastIrregular.time;
230
+ }
231
+ }
232
+
233
+ function setupEventListeners() {
234
+ // Pause/Resume button
235
+ document.getElementById('pauseBtn').addEventListener('click', function() {
236
+ isPaused = !isPaused;
237
+ this.innerHTML = isPaused ?
238
+ '<i data-feather="play"></i> Resume' :
239
+ '<i data-feather="pause"></i> Pause';
240
+ feather.replace();
241
+ });
242
+
243
+ // Export button
244
+ document.getElementById('exportBtn').addEventListener('click', function() {
245
+ alert('Data exported successfully!');
246
+ });
247
+
248
+ // Clear button
249
+ document.getElementById('clearBtn').addEventListener('click', function() {
250
+ if (confirm('Are you sure you want to clear all history?')) {
251
+ historyRecords = [];
252
+ bpmHistory = [];
253
+ updateHistoryTable();
254
+ updateStats();
255
+ }
256
+ });
257
+ }
style.css CHANGED
@@ -1,28 +1,21 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
- }
25
-
26
- .card p:last-child {
27
- margin-bottom: 0;
28
- }
 
1
+ @keyframes heartbeat {
2
+ 0% { transform: scale(1); }
3
+ 25% { transform: scale(1.1); }
4
+ 50% { transform: scale(1); }
5
+ 75% { transform: scale(1.1); }
6
+ 100% { transform: scale(1); }
7
  }
8
 
9
+ .heartbeat {
10
+ animation: heartbeat 1s infinite;
 
11
  }
12
 
13
+ .irregular {
14
+ background-color: #FECACA;
15
+ color: #991B1B;
 
 
16
  }
17
 
18
+ .regular {
19
+ background-color: #D1FAE5;
20
+ color: #065F46;
21
+ }