andersonhuang commited on
Commit
92cdb54
·
verified ·
1 Parent(s): 6fc7eb3

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +1278 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Plmtools
3
- emoji: 📉
4
- colorFrom: yellow
5
  colorTo: blue
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: plmtools
3
+ emoji: 🐳
4
+ colorFrom: blue
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1278 @@
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>Protein Sequence Analysis Toolkit</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500;700&family=Roboto:wght@300;400;500;700&display=swap');
11
+
12
+ :root {
13
+ --primary: #3b82f6;
14
+ --primary-dark: #2563eb;
15
+ --secondary: #10b981;
16
+ --dark: #1e293b;
17
+ --light: #f8fafc;
18
+ }
19
+
20
+ body {
21
+ font-family: 'Roboto', sans-serif;
22
+ background-color: #f1f5f9;
23
+ color: var(--dark);
24
+ }
25
+
26
+ .mono {
27
+ font-family: 'Roboto Mono', monospace;
28
+ }
29
+
30
+ .sequence-display {
31
+ background-color: #e2e8f0;
32
+ border-radius: 0.5rem;
33
+ padding: 1rem;
34
+ overflow-x: auto;
35
+ white-space: nowrap;
36
+ }
37
+
38
+ .amino-acid {
39
+ display: inline-block;
40
+ width: 1.5rem;
41
+ text-align: center;
42
+ font-weight: 500;
43
+ position: relative;
44
+ }
45
+
46
+ .hydrophobic { color: #1e40af; background-color: #bfdbfe; }
47
+ .hydrophilic { color: #166534; background-color: #bbf7d0; }
48
+ .neutral { color: #713f12; background-color: #fed7aa; }
49
+ .acidic { color: #9d174d; background-color: #f9a8d4; }
50
+ .basic { color: #6d28d9; background-color: #ddd6fe; }
51
+ .cysteine { color: #854d0e; background-color: #fef08a; }
52
+ .proline { color: #0e7490; background-color: #a5f3fc; }
53
+
54
+ .helix { background-color: rgba(239, 68, 68, 0.2); }
55
+ .sheet { background-color: rgba(16, 185, 129, 0.2); }
56
+ .coil { background-color: rgba(156, 163, 175, 0.2); }
57
+
58
+ .tooltip {
59
+ position: relative;
60
+ display: inline-block;
61
+ }
62
+
63
+ .tooltip .tooltiptext {
64
+ visibility: hidden;
65
+ width: 120px;
66
+ background-color: #555;
67
+ color: #fff;
68
+ text-align: center;
69
+ border-radius: 6px;
70
+ padding: 5px;
71
+ position: absolute;
72
+ z-index: 1;
73
+ bottom: 125%;
74
+ left: 50%;
75
+ margin-left: -60px;
76
+ opacity: 0;
77
+ transition: opacity 0.3s;
78
+ font-size: 0.8rem;
79
+ }
80
+
81
+ .tooltip:hover .tooltiptext {
82
+ visibility: visible;
83
+ opacity: 1;
84
+ }
85
+
86
+ .tab-content {
87
+ display: none;
88
+ }
89
+
90
+ .tab-content.active {
91
+ display: block;
92
+ animation: fadeIn 0.3s ease-in-out;
93
+ }
94
+
95
+ @keyframes fadeIn {
96
+ from { opacity: 0; transform: translateY(10px); }
97
+ to { opacity: 1; transform: translateY(0); }
98
+ }
99
+
100
+ .feature-badge {
101
+ display: inline-flex;
102
+ align-items: center;
103
+ padding: 0.25rem 0.5rem;
104
+ border-radius: 9999px;
105
+ font-size: 0.75rem;
106
+ font-weight: 500;
107
+ margin-right: 0.5rem;
108
+ margin-bottom: 0.5rem;
109
+ }
110
+
111
+ .feature-badge i {
112
+ margin-right: 0.25rem;
113
+ }
114
+
115
+ .chart-container {
116
+ position: relative;
117
+ height: 300px;
118
+ width: 100%;
119
+ }
120
+
121
+ .loading-spinner {
122
+ border: 4px solid rgba(0, 0, 0, 0.1);
123
+ border-radius: 50%;
124
+ border-top: 4px solid var(--primary);
125
+ width: 40px;
126
+ height: 40px;
127
+ animation: spin 1s linear infinite;
128
+ margin: 2rem auto;
129
+ }
130
+
131
+ @keyframes spin {
132
+ 0% { transform: rotate(0deg); }
133
+ 100% { transform: rotate(360deg); }
134
+ }
135
+
136
+ .result-card {
137
+ transition: all 0.3s ease;
138
+ }
139
+
140
+ .result-card:hover {
141
+ transform: translateY(-5px);
142
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
143
+ }
144
+
145
+ .sequence-input {
146
+ min-height: 100px;
147
+ font-family: 'Roboto Mono', monospace;
148
+ }
149
+
150
+ .analysis-section {
151
+ scroll-margin-top: 100px;
152
+ }
153
+ </style>
154
+ </head>
155
+ <body class="min-h-screen">
156
+ <div class="container mx-auto px-4 py-8 max-w-7xl">
157
+ <!-- Header -->
158
+ <header class="mb-8 text-center">
159
+ <h1 class="text-4xl font-bold text-blue-600 mb-2">Protein Sequence Analysis Toolkit</h1>
160
+ <p class="text-lg text-gray-600">Comprehensive analysis of protein and peptide sequences using advanced protein language models</p>
161
+ </header>
162
+
163
+ <!-- Main Content -->
164
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden">
165
+ <!-- Input Section -->
166
+ <div class="p-6 border-b border-gray-200">
167
+ <div class="flex flex-col md:flex-row gap-6">
168
+ <div class="flex-1">
169
+ <label for="sequence-input" class="block text-sm font-medium text-gray-700 mb-2">Enter Protein/Peptide Sequence</label>
170
+ <textarea id="sequence-input" class="w-full px-4 py-3 border border-gray-300 rounded-lg sequence-input focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter amino acid sequence (e.g., MAEGEITTFTALTEKFNLPPGNYKKPKLLYCSNGGHFLRILPDGTVDGTRDRSDQHIQLQLSAESVGEVYIKSTETGQYLAMDTSGLLYGSQTPSEECLFLERLEENHYNTYTSKKHAEKNWFVGLKKNGSCKRGPRTHYGQKAILFLPLPV)"></textarea>
171
+ <div class="flex flex-wrap gap-2 mt-3">
172
+ <button id="clear-btn" class="px-3 py-1 bg-gray-200 text-gray-700 rounded-md text-sm hover:bg-gray-300">Clear</button>
173
+ <button id="example-btn" class="px-3 py-1 bg-blue-100 text-blue-700 rounded-md text-sm hover:bg-blue-200">Load Example</button>
174
+ <button id="analyze-btn" class="px-3 py-1 bg-blue-600 text-white rounded-md text-sm hover:bg-blue-700">Analyze Sequence</button>
175
+ </div>
176
+ </div>
177
+ <div class="flex-1">
178
+ <label class="block text-sm font-medium text-gray-700 mb-2">Sequence Features</label>
179
+ <div class="bg-gray-50 p-4 rounded-lg h-full">
180
+ <div id="sequence-stats" class="grid grid-cols-2 gap-2">
181
+ <div class="text-sm">
182
+ <span class="text-gray-500">Length:</span>
183
+ <span id="seq-length" class="font-medium">0</span>
184
+ </div>
185
+ <div class="text-sm">
186
+ <span class="text-gray-500">Molecular Weight:</span>
187
+ <span id="mol-weight" class="font-medium">0 Da</span>
188
+ </div>
189
+ <div class="text-sm">
190
+ <span class="text-gray-500">Isoelectric Point:</span>
191
+ <span id="isoelectric-pt" class="font-medium">-</span>
192
+ </div>
193
+ <div class="text-sm">
194
+ <span class="text-gray-500">Extinction Coefficient:</span>
195
+ <span id="ext-coeff" class="font-medium">-</span>
196
+ </div>
197
+ <div class="text-sm col-span-2">
198
+ <span class="text-gray-500">Amino Acid Composition:</span>
199
+ <div id="aa-composition" class="flex flex-wrap gap-1 mt-1"></div>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ </div>
206
+
207
+ <!-- Results Section -->
208
+ <div id="results-section" class="hidden">
209
+ <!-- Tabs Navigation -->
210
+ <div class="border-b border-gray-200">
211
+ <nav class="flex overflow-x-auto">
212
+ <button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:text-blue-600 hover:border-blue-300" data-tab="sequence">Sequence</button>
213
+ <button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:text-blue-600 hover:border-blue-300" data-tab="physicochemical">Physicochemical</button>
214
+ <button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:text-blue-600 hover:border-blue-300" data-tab="structure">Structure</button>
215
+ <button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:text-blue-600 hover:border-blue-300" data-tab="functional">Functional</button>
216
+ <button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:text-blue-600 hover:border-blue-300" data-tab="optimization">Optimization</button>
217
+ </nav>
218
+ </div>
219
+
220
+ <!-- Tab Contents -->
221
+ <div class="p-6">
222
+ <!-- Sequence Tab -->
223
+ <div id="sequence-tab" class="tab-content active">
224
+ <div class="mb-6">
225
+ <h3 class="text-lg font-semibold mb-3">Sequence Visualization</h3>
226
+ <div id="sequence-display" class="sequence-display mono"></div>
227
+ </div>
228
+
229
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
230
+ <div>
231
+ <h3 class="text-lg font-semibold mb-3">Amino Acid Properties</h3>
232
+ <div id="property-legend" class="bg-gray-50 p-4 rounded-lg">
233
+ <div class="flex flex-wrap gap-2 mb-2">
234
+ <span class="feature-badge hydrophobic"><i class="fas fa-water"></i> Hydrophobic</span>
235
+ <span class="feature-badge hydrophilic"><i class="fas fa-tint"></i> Hydrophilic</span>
236
+ <span class="feature-badge acidic"><i class="fas fa-minus-circle"></i> Acidic</span>
237
+ <span class="feature-badge basic"><i class="fas fa-plus-circle"></i> Basic</span>
238
+ <span class="feature-badge neutral"><i class="fas fa-circle"></i> Neutral</span>
239
+ <span class="feature-badge cysteine"><i class="fas fa-link"></i> Cysteine</span>
240
+ <span class="feature-badge proline"><i class="fas fa-undo"></i> Proline</span>
241
+ </div>
242
+ </div>
243
+ </div>
244
+
245
+ <div>
246
+ <h3 class="text-lg font-semibold mb-3">Secondary Structure</h3>
247
+ <div id="structure-legend" class="bg-gray-50 p-4 rounded-lg">
248
+ <div class="flex flex-wrap gap-2 mb-2">
249
+ <span class="feature-badge helix"><i class="fas fa-helix"></i> Helix</span>
250
+ <span class="feature-badge sheet"><i class="fas fa-layer-group"></i> Sheet</span>
251
+ <span class="feature-badge coil"><i class="fas fa-wave-square"></i> Coil</span>
252
+ </div>
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ <!-- Physicochemical Tab -->
259
+ <div id="physicochemical-tab" class="tab-content">
260
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
261
+ <div class="analysis-section">
262
+ <h3 class="text-lg font-semibold mb-3">Isoelectric Point</h3>
263
+ <div class="bg-gray-50 p-4 rounded-lg">
264
+ <div class="flex items-center justify-between mb-2">
265
+ <span class="text-gray-700">Calculated pI:</span>
266
+ <span id="pI-value" class="text-xl font-bold text-blue-600">7.2</span>
267
+ </div>
268
+ <div class="w-full bg-gray-200 rounded-full h-4">
269
+ <div id="pI-bar" class="bg-blue-600 h-4 rounded-full" style="width: 50%"></div>
270
+ </div>
271
+ <div class="flex justify-between text-xs text-gray-500 mt-1">
272
+ <span>3</span>
273
+ <span>7</span>
274
+ <span>11</span>
275
+ </div>
276
+ <p class="text-sm text-gray-600 mt-2">The isoelectric point (pI) is the pH at which the protein has no net charge.</p>
277
+ </div>
278
+ </div>
279
+
280
+ <div class="analysis-section">
281
+ <h3 class="text-lg font-semibold mb-3">Molecular Weight</h3>
282
+ <div class="bg-gray-50 p-4 rounded-lg">
283
+ <div class="flex items-center justify-between mb-2">
284
+ <span class="text-gray-700">Calculated MW:</span>
285
+ <span id="mw-value" class="text-xl font-bold text-green-600">12,345 Da</span>
286
+ </div>
287
+ <p class="text-sm text-gray-600">Molecular weight calculated from the sum of amino acid residues.</p>
288
+ </div>
289
+ </div>
290
+
291
+ <div class="analysis-section">
292
+ <h3 class="text-lg font-semibold mb-3">Extinction Coefficient</h3>
293
+ <div class="bg-gray-50 p-4 rounded-lg">
294
+ <div class="flex items-center justify-between mb-2">
295
+ <span class="text-gray-700">ε<sub>280</sub> (M<sup>-1</sup>cm<sup>-1</sup>):</span>
296
+ <span id="ext-coeff-value" class="text-xl font-bold text-purple-600">44,720</span>
297
+ </div>
298
+ <p class="text-sm text-gray-600">Calculated from the number of Trp, Tyr, and Cys residues.</p>
299
+ </div>
300
+ </div>
301
+
302
+ <div class="analysis-section">
303
+ <h3 class="text-lg font-semibold mb-3">Hydrophobicity Analysis</h3>
304
+ <div class="bg-gray-50 p-4 rounded-lg">
305
+ <div class="chart-container">
306
+ <canvas id="hydrophobicity-chart"></canvas>
307
+ </div>
308
+ <p class="text-sm text-gray-600 mt-2">Hydrophobicity profile calculated using the Kyte-Doolittle scale.</p>
309
+ </div>
310
+ </div>
311
+ </div>
312
+ </div>
313
+
314
+ <!-- Structure Tab -->
315
+ <div id="structure-tab" class="tab-content">
316
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
317
+ <div class="analysis-section">
318
+ <h3 class="text-lg font-semibold mb-3">Secondary Structure Prediction</h3>
319
+ <div class="bg-gray-50 p-4 rounded-lg">
320
+ <div class="chart-container">
321
+ <canvas id="secondary-structure-chart"></canvas>
322
+ </div>
323
+ <p class="text-sm text-gray-600 mt-2">Predicted using a protein language model (ESM-2).</p>
324
+ </div>
325
+ </div>
326
+
327
+ <div class="analysis-section">
328
+ <h3 class="text-lg font-semibold mb-3">Disorder Prediction</h3>
329
+ <div class="bg-gray-50 p-4 rounded-lg">
330
+ <div class="chart-container">
331
+ <canvas id="disorder-chart"></canvas>
332
+ </div>
333
+ <p class="text-sm text-gray-600 mt-2">Predicted intrinsic disorder using IUPred2A.</p>
334
+ </div>
335
+ </div>
336
+
337
+ <div class="analysis-section">
338
+ <h3 class="text-lg font-semibold mb-3">Solvent Accessibility</h3>
339
+ <div class="bg-gray-50 p-4 rounded-lg">
340
+ <div class="chart-container">
341
+ <canvas id="accessibility-chart"></canvas>
342
+ </div>
343
+ <p class="text-sm text-gray-600 mt-2">Relative solvent accessible surface area (RSA) prediction.</p>
344
+ </div>
345
+ </div>
346
+
347
+ <div class="analysis-section">
348
+ <h3 class="text-lg font-semibold mb-3">Transmembrane Regions</h3>
349
+ <div class="bg-gray-50 p-4 rounded-lg">
350
+ <div class="chart-container">
351
+ <canvas id="transmembrane-chart"></canvas>
352
+ </div>
353
+ <p class="text-sm text-gray-600 mt-2">Predicted using TMHMM.</p>
354
+ </div>
355
+ </div>
356
+ </div>
357
+ </div>
358
+
359
+ <!-- Functional Tab -->
360
+ <div id="functional-tab" class="tab-content">
361
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
362
+ <div class="analysis-section">
363
+ <h3 class="text-lg font-semibold mb-3">Signal Peptide Prediction</h3>
364
+ <div class="bg-gray-50 p-4 rounded-lg">
365
+ <div class="flex items-center justify-between mb-2">
366
+ <span class="text-gray-700">Prediction:</span>
367
+ <span id="signal-peptide-value" class="text-xl font-bold text-blue-600">Present (1-24)</span>
368
+ </div>
369
+ <div class="w-full bg-gray-200 rounded-full h-4">
370
+ <div id="signal-peptide-bar" class="bg-blue-600 h-4 rounded-full" style="width: 20%"></div>
371
+ </div>
372
+ <p class="text-sm text-gray-600 mt-2">Predicted using SignalP-6.0.</p>
373
+ </div>
374
+ </div>
375
+
376
+ <div class="analysis-section">
377
+ <h3 class="text-lg font-semibold mb-3">Motif Analysis</h3>
378
+ <div class="bg-gray-50 p-4 rounded-lg">
379
+ <div id="motif-results">
380
+ <div class="mb-3">
381
+ <div class="flex justify-between mb-1">
382
+ <span class="text-sm font-medium text-gray-700">N-glycosylation (N-X-S/T)</span>
383
+ <span class="text-sm font-medium text-blue-600">3 sites</span>
384
+ </div>
385
+ <div class="w-full bg-gray-200 rounded-full h-2">
386
+ <div class="bg-blue-600 h-2 rounded-full" style="width: 45%"></div>
387
+ </div>
388
+ </div>
389
+ <div class="mb-3">
390
+ <div class="flex justify-between mb-1">
391
+ <span class="text-sm font-medium text-gray-700">Phosphorylation (S/T/Y)</span>
392
+ <span class="text-sm font-medium text-green-600">8 sites</span>
393
+ </div>
394
+ <div class="w-full bg-gray-200 rounded-full h-2">
395
+ <div class="bg-green-600 h-2 rounded-full" style="width: 70%"></div>
396
+ </div>
397
+ </div>
398
+ <div class="mb-3">
399
+ <div class="flex justify-between mb-1">
400
+ <span class="text-sm font-medium text-gray-700">SH3 binding (P-X-X-P)</span>
401
+ <span class="text-sm font-medium text-purple-600">2 sites</span>
402
+ </div>
403
+ <div class="w-full bg-gray-200 rounded-full h-2">
404
+ <div class="bg-purple-600 h-2 rounded-full" style="width: 20%"></div>
405
+ </div>
406
+ </div>
407
+ </div>
408
+ <p class="text-sm text-gray-600 mt-2">Common functional motifs identified in the sequence.</p>
409
+ </div>
410
+ </div>
411
+
412
+ <div class="analysis-section">
413
+ <h3 class="text-lg font-semibold mb-3">Cytotoxicity Prediction</h3>
414
+ <div class="bg-gray-50 p-4 rounded-lg">
415
+ <div class="flex items-center justify-between mb-2">
416
+ <span class="text-gray-700">Prediction:</span>
417
+ <span id="cytotoxicity-value" class="text-xl font-bold text-red-600">Low risk</span>
418
+ </div>
419
+ <div class="w-full bg-gray-200 rounded-full h-4">
420
+ <div id="cytotoxicity-bar" class="bg-red-600 h-4 rounded-full" style="width: 30%"></div>
421
+ </div>
422
+ <p class="text-sm text-gray-600 mt-2">Predicted using a machine learning model trained on cytotoxic peptides.</p>
423
+ </div>
424
+ </div>
425
+
426
+ <div class="analysis-section">
427
+ <h3 class="text-lg font-semibold mb-3">Saturation Mutagenesis Analysis</h3>
428
+ <div class="bg-gray-50 p-4 rounded-lg">
429
+ <div class="mb-4">
430
+ <label for="motif-select" class="block text-sm font-medium text-gray-700 mb-2">Select Motif for Mutagenesis</label>
431
+ <select id="motif-select" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">
432
+ <option>N-glycosylation (N-X-S/T) at 45-47</option>
433
+ <option>Phosphorylation (S/T) at 78</option>
434
+ <option>SH3 binding (P-X-X-P) at 102-105</option>
435
+ </select>
436
+ </div>
437
+ <button id="run-mutagenesis-btn" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">Run Saturation Mutagenesis</button>
438
+ <div id="mutagenesis-results" class="mt-4 hidden">
439
+ <h4 class="font-medium text-gray-700 mb-2">Mutation Impact Summary</h4>
440
+ <div class="overflow-x-auto">
441
+ <table class="min-w-full divide-y divide-gray-200">
442
+ <thead class="bg-gray-50">
443
+ <tr>
444
+ <th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Position</th>
445
+ <th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Mutation</th>
446
+ <th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Stability ΔΔG</th>
447
+ <th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Function Impact</th>
448
+ </tr>
449
+ </thead>
450
+ <tbody class="bg-white divide-y divide-gray-200 text-sm">
451
+ <tr>
452
+ <td class="px-3 py-2">N45</td>
453
+ <td class="px-3 py-2">N45A</td>
454
+ <td class="px-3 py-2 text-red-600">+1.2</td>
455
+ <td class="px-3 py-2">Disrupts glycosylation</td>
456
+ </tr>
457
+ <tr>
458
+ <td class="px-3 py-2">N45</td>
459
+ <td class="px-3 py-2">N45D</td>
460
+ <td class="px-3 py-2 text-red-600">+0.8</td>
461
+ <td class="px-3 py-2">Disrupts glycosylation</td>
462
+ </tr>
463
+ <tr>
464
+ <td class="px-3 py-2">N45</td>
465
+ <td class="px-3 py-2">N45Q</td>
466
+ <td class="px-3 py-2 text-green-600">-0.2</td>
467
+ <td class="px-3 py-2">Maintains glycosylation</td>
468
+ </tr>
469
+ </tbody>
470
+ </table>
471
+ </div>
472
+ </div>
473
+ </div>
474
+ </div>
475
+ </div>
476
+ </div>
477
+
478
+ <!-- Optimization Tab -->
479
+ <div id="optimization-tab" class="tab-content">
480
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
481
+ <div class="analysis-section">
482
+ <h3 class="text-lg font-semibold mb-3">Sequence Optimization</h3>
483
+ <div class="bg-gray-50 p-4 rounded-lg">
484
+ <div class="mb-4">
485
+ <label class="block text-sm font-medium text-gray-700 mb-2">Optimization Goals</label>
486
+ <div class="space-y-2">
487
+ <div class="flex items-center">
488
+ <input id="opt-stability" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
489
+ <label for="opt-stability" class="ml-2 block text-sm text-gray-700">Improve stability</label>
490
+ </div>
491
+ <div class="flex items-center">
492
+ <input id="opt-expression" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
493
+ <label for="opt-expression" class="ml-2 block text-sm text-gray-700">Improve expression</label>
494
+ </div>
495
+ <div class="flex items-center">
496
+ <input id="opt-solubility" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
497
+ <label for="opt-solubility" class="ml-2 block text-sm text-gray-700">Improve solubility</label>
498
+ </div>
499
+ <div class="flex items-center">
500
+ <input id="opt-function" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
501
+ <label for="opt-function" class="ml-2 block text-sm text-gray-700">Maintain function</label>
502
+ </div>
503
+ </div>
504
+ </div>
505
+ <button id="run-optimization-btn" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">Run Optimization</button>
506
+ <div id="optimization-results" class="mt-4 hidden">
507
+ <h4 class="font-medium text-gray-700 mb-2">Optimized Sequence</h4>
508
+ <div class="sequence-display mono mb-3"></div>
509
+ <div class="grid grid-cols-2 gap-4">
510
+ <div>
511
+ <span class="text-sm text-gray-500">Original Stability Score:</span>
512
+ <span class="font-medium">0.65</span>
513
+ </div>
514
+ <div>
515
+ <span class="text-sm text-gray-500">Optimized Stability Score:</span>
516
+ <span class="font-medium text-green-600">0.82</span>
517
+ </div>
518
+ <div>
519
+ <span class="text-sm text-gray-500">Original Expression Score:</span>
520
+ <span class="font-medium">0.45</span>
521
+ </div>
522
+ <div>
523
+ <span class="text-sm text-gray-500">Optimized Expression Score:</span>
524
+ <span class="font-medium text-green-600">0.78</span>
525
+ </div>
526
+ </div>
527
+ <div class="mt-3">
528
+ <h5 class="text-sm font-medium text-gray-700 mb-1">Key Changes:</h5>
529
+ <ul class="text-sm list-disc pl-5 space-y-1">
530
+ <li>R32K: Improved stability without affecting function</li>
531
+ <li>L45V: Improved solubility</li>
532
+ <li>P78A: Removed aggregation-prone proline</li>
533
+ </ul>
534
+ </div>
535
+ </div>
536
+ </div>
537
+ </div>
538
+
539
+ <div class="analysis-section">
540
+ <h3 class="text-lg font-semibold mb-3">Protein Language Model Features</h3>
541
+ <div class="bg-gray-50 p-4 rounded-lg">
542
+ <div class="mb-4">
543
+ <label for="model-select" class="block text-sm font-medium text-gray-700 mb-2">Select Model</label>
544
+ <select id="model-select" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">
545
+ <option>ESM-2 (650M parameters)</option>
546
+ <option>ProtT5-XL (3B parameters)</option>
547
+ <option>AlphaFold2 (with ESM-1b)</option>
548
+ <option>ESM-1v (evolutionary model)</option>
549
+ </select>
550
+ </div>
551
+ <div class="mb-4">
552
+ <label class="block text-sm font-medium text-gray-700 mb-2">Feature Extraction</label>
553
+ <div class="space-y-2">
554
+ <div class="flex items-center">
555
+ <input id="feat-embedding" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
556
+ <label for="feat-embedding" class="ml-2 block text-sm text-gray-700">Per-residue embeddings</label>
557
+ </div>
558
+ <div class="flex items-center">
559
+ <input id="feat-contact" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
560
+ <label for="feat-contact" class="ml-2 block text-sm text-gray-700">Contact map</label>
561
+ </div>
562
+ <div class="flex items-center">
563
+ <input id="feat-conservation" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
564
+ <label for="feat-conservation" class="ml-2 block text-sm text-gray-700">Evolutionary conservation</label>
565
+ </div>
566
+ </div>
567
+ </div>
568
+ <button id="run-model-btn" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">Extract Features</button>
569
+ <div id="model-results" class="mt-4 hidden">
570
+ <div class="chart-container">
571
+ <canvas id="model-embedding-chart"></canvas>
572
+ </div>
573
+ <p class="text-sm text-gray-600 mt-2">Per-residue embeddings reduced to 2D using UMAP.</p>
574
+ </div>
575
+ </div>
576
+ </div>
577
+ </div>
578
+ </div>
579
+ </div>
580
+ </div>
581
+
582
+ <!-- Loading State -->
583
+ <div id="loading-section" class="hidden p-12 text-center">
584
+ <div class="loading-spinner"></div>
585
+ <h3 class="text-lg font-medium text-gray-700 mt-4">Analyzing protein sequence...</h3>
586
+ <p class="text-sm text-gray-500 mt-1">This may take a few moments as we run multiple predictions.</p>
587
+ <div class="w-full bg-gray-200 rounded-full h-2.5 mt-6 max-w-md mx-auto">
588
+ <div id="progress-bar" class="bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div>
589
+ </div>
590
+ <p id="progress-text" class="text-xs text-gray-500 mt-2">Initializing models...</p>
591
+ </div>
592
+ </div>
593
+
594
+ <!-- Footer -->
595
+ <footer class="mt-8 text-center text-sm text-gray-500">
596
+ <p>Protein Sequence Analysis Toolkit v1.0 - Powered by ESM-2, ProtT5, and other protein language models</p>
597
+ <p class="mt-1">© 2023 Protein Analysis Group. All rights reserved.</p>
598
+ </footer>
599
+ </div>
600
+
601
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
602
+ <script>
603
+ document.addEventListener('DOMContentLoaded', function() {
604
+ // Tab functionality
605
+ const tabButtons = document.querySelectorAll('.tab-btn');
606
+ const tabContents = document.querySelectorAll('.tab-content');
607
+
608
+ tabButtons.forEach(button => {
609
+ button.addEventListener('click', () => {
610
+ // Remove active class from all buttons and contents
611
+ tabButtons.forEach(btn => btn.classList.remove('border-blue-600', 'text-blue-600'));
612
+ tabContents.forEach(content => content.classList.remove('active'));
613
+
614
+ // Add active class to clicked button
615
+ button.classList.add('border-blue-600', 'text-blue-600');
616
+
617
+ // Show corresponding content
618
+ const tabId = button.getAttribute('data-tab') + '-tab';
619
+ document.getElementById(tabId).classList.add('active');
620
+ });
621
+ });
622
+
623
+ // Example sequence button
624
+ document.getElementById('example-btn').addEventListener('click', function() {
625
+ const exampleSeq = "MAEGEITTFTALTEKFNLPPGNYKKPKLLYCSNGGHFLRILPDGTVDGTRDRSDQHIQLQLSAESVGEVYIKSTETGQYLAMDTSGLLYGSQTPSEECLFLERLEENHYNTYTSKKHAEKNWFVGLKKNGSCKRGPRTHYGQKAILFLPLPV";
626
+ document.getElementById('sequence-input').value = exampleSeq;
627
+ updateSequenceStats(exampleSeq);
628
+ });
629
+
630
+ // Clear button
631
+ document.getElementById('clear-btn').addEventListener('click', function() {
632
+ document.getElementById('sequence-input').value = '';
633
+ document.getElementById('sequence-display').innerHTML = '';
634
+ document.getElementById('seq-length').textContent = '0';
635
+ document.getElementById('mol-weight').textContent = '0 Da';
636
+ document.getElementById('isoelectric-pt').textContent = '-';
637
+ document.getElementById('ext-coeff').textContent = '-';
638
+ document.getElementById('aa-composition').innerHTML = '';
639
+ document.getElementById('results-section').classList.add('hidden');
640
+ });
641
+
642
+ // Analyze button
643
+ document.getElementById('analyze-btn').addEventListener('click', function() {
644
+ const sequence = document.getElementById('sequence-input').value.trim().toUpperCase();
645
+
646
+ if (!sequence) {
647
+ alert('Please enter a protein sequence');
648
+ return;
649
+ }
650
+
651
+ if (!/^[ACDEFGHIKLMNPQRSTVWY]+$/i.test(sequence)) {
652
+ alert('Invalid amino acid characters detected. Please enter a valid protein sequence.');
653
+ return;
654
+ }
655
+
656
+ // Show loading state
657
+ document.getElementById('results-section').classList.add('hidden');
658
+ document.getElementById('loading-section').classList.remove('hidden');
659
+
660
+ // Simulate analysis progress
661
+ simulateAnalysisProgress();
662
+
663
+ // After "analysis" is complete
664
+ setTimeout(() => {
665
+ document.getElementById('loading-section').classList.add('hidden');
666
+ document.getElementById('results-section').classList.remove('hidden');
667
+ analyzeSequence(sequence);
668
+ }, 3000);
669
+ });
670
+
671
+ // Sequence input listener
672
+ document.getElementById('sequence-input').addEventListener('input', function() {
673
+ const sequence = this.value.trim().toUpperCase();
674
+ updateSequenceStats(sequence);
675
+ });
676
+
677
+ // Run mutagenesis button
678
+ document.getElementById('run-mutagenesis-btn').addEventListener('click', function() {
679
+ document.getElementById('mutagenesis-results').classList.remove('hidden');
680
+ // Scroll to results
681
+ document.getElementById('mutagenesis-results').scrollIntoView({ behavior: 'smooth' });
682
+ });
683
+
684
+ // Run optimization button
685
+ document.getElementById('run-optimization-btn').addEventListener('click', function() {
686
+ document.getElementById('optimization-results').classList.remove('hidden');
687
+ // Scroll to results
688
+ document.getElementById('optimization-results').scrollIntoView({ behavior: 'smooth' });
689
+ });
690
+
691
+ // Run model button
692
+ document.getElementById('run-model-btn').addEventListener('click', function() {
693
+ document.getElementById('model-results').classList.remove('hidden');
694
+ // Scroll to results
695
+ document.getElementById('model-results').scrollIntoView({ behavior: 'smooth' });
696
+
697
+ // Create embedding visualization
698
+ createEmbeddingChart();
699
+ });
700
+
701
+ // Function to update sequence statistics
702
+ function updateSequenceStats(sequence) {
703
+ if (!sequence) {
704
+ document.getElementById('seq-length').textContent = '0';
705
+ document.getElementById('mol-weight').textContent = '0 Da';
706
+ document.getElementById('isoelectric-pt').textContent = '-';
707
+ document.getElementById('ext-coeff').textContent = '-';
708
+ document.getElementById('aa-composition').innerHTML = '';
709
+ return;
710
+ }
711
+
712
+ // Calculate length
713
+ document.getElementById('seq-length').textContent = sequence.length;
714
+
715
+ // Calculate molecular weight (simplified)
716
+ const aaWeights = {
717
+ 'A': 89.09, 'R': 174.20, 'N': 132.12, 'D': 133.10, 'C': 121.15,
718
+ 'E': 147.13, 'Q': 146.15, 'G': 75.07, 'H': 155.16, 'I': 131.17,
719
+ 'L': 131.17, 'K': 146.19, 'M': 149.21, 'F': 165.19, 'P': 115.13,
720
+ 'S': 105.09, 'T': 119.12, 'W': 204.23, 'Y': 181.19, 'V': 117.15
721
+ };
722
+
723
+ let molWeight = 18.02; // Water
724
+ for (let aa of sequence) {
725
+ molWeight += aaWeights[aa] || 0;
726
+ }
727
+ document.getElementById('mol-weight').textContent = molWeight.toFixed(2) + ' Da';
728
+
729
+ // Calculate amino acid composition
730
+ const aaCount = {};
731
+ for (let aa of sequence) {
732
+ aaCount[aa] = (aaCount[aa] || 0) + 1;
733
+ }
734
+
735
+ let aaCompHTML = '';
736
+ for (let aa in aaCount) {
737
+ const percentage = ((aaCount[aa] / sequence.length) * 100).toFixed(1);
738
+ aaCompHTML += `<span class="amino-acid ${getAAClass(aa)}">${aa}: ${aaCount[aa]} (${percentage}%)</span>`;
739
+ }
740
+ document.getElementById('aa-composition').innerHTML = aaCompHTML;
741
+
742
+ // Display sequence with coloring
743
+ displaySequence(sequence);
744
+ }
745
+
746
+ // Function to display sequence with coloring
747
+ function displaySequence(sequence) {
748
+ let seqHTML = '';
749
+ for (let i = 0; i < sequence.length; i++) {
750
+ const aa = sequence[i];
751
+ const aaClass = getAAClass(aa);
752
+ seqHTML += `<span class="amino-acid ${aaClass} tooltip">${aa}<span class="tooltiptext">${getAAName(aa)} (Pos ${i+1})</span></span>`;
753
+ }
754
+ document.getElementById('sequence-display').innerHTML = seqHTML;
755
+ }
756
+
757
+ // Function to get amino acid class for styling
758
+ function getAAClass(aa) {
759
+ const hydrophobic = ['A', 'V', 'L', 'I', 'M', 'F', 'W', 'Y'];
760
+ const hydrophilic = ['S', 'T', 'N', 'Q'];
761
+ const acidic = ['D', 'E'];
762
+ const basic = ['K', 'R', 'H'];
763
+
764
+ if (aa === 'C') return 'cysteine';
765
+ if (aa === 'P') return 'proline';
766
+ if (hydrophobic.includes(aa)) return 'hydrophobic';
767
+ if (hydrophilic.includes(aa)) return 'hydrophilic';
768
+ if (acidic.includes(aa)) return 'acidic';
769
+ if (basic.includes(aa)) return 'basic';
770
+ return 'neutral';
771
+ }
772
+
773
+ // Function to get amino acid name
774
+ function getAAName(aa) {
775
+ const aaNames = {
776
+ 'A': 'Alanine', 'R': 'Arginine', 'N': 'Asparagine', 'D': 'Aspartic acid',
777
+ 'C': 'Cysteine', 'E': 'Glutamic acid', 'Q': 'Glutamine', 'G': 'Glycine',
778
+ 'H': 'Histidine', 'I': 'Isoleucine', 'L': 'Leucine', 'K': 'Lysine',
779
+ 'M': 'Methionine', 'F': 'Phenylalanine', 'P': 'Proline', 'S': 'Serine',
780
+ 'T': 'Threonine', 'W': 'Tryptophan', 'Y': 'Tyrosine', 'V': 'Valine'
781
+ };
782
+ return aaNames[aa] || aa;
783
+ }
784
+
785
+ // Function to simulate analysis progress
786
+ function simulateAnalysisProgress() {
787
+ const progressStages = [
788
+ "Initializing models...",
789
+ "Calculating physicochemical properties...",
790
+ "Predicting secondary structure...",
791
+ "Analyzing functional motifs...",
792
+ "Running language model...",
793
+ "Finalizing results..."
794
+ ];
795
+
796
+ let progress = 0;
797
+ const progressBar = document.getElementById('progress-bar');
798
+ const progressText = document.getElementById('progress-text');
799
+
800
+ const interval = setInterval(() => {
801
+ progress += Math.random() * 10;
802
+ if (progress > 100) progress = 100;
803
+ progressBar.style.width = `${progress}%`;
804
+
805
+ // Update progress text based on stage
806
+ const stageIndex = Math.min(Math.floor(progress / (100 / progressStages.length)), progressStages.length - 1);
807
+ progressText.textContent = progressStages[stageIndex];
808
+
809
+ if (progress >= 100) {
810
+ clearInterval(interval);
811
+ progressText.textContent = "Analysis complete!";
812
+ }
813
+ }, 300);
814
+ }
815
+
816
+ // Function to analyze sequence (main analysis)
817
+ function analyzeSequence(sequence) {
818
+ // Update sequence stats
819
+ updateSequenceStats(sequence);
820
+
821
+ // Calculate isoelectric point (simplified)
822
+ const pI = calculateIsoelectricPoint(sequence);
823
+ document.getElementById('pI-value').textContent = pI.toFixed(2);
824
+ document.getElementById('pI-bar').style.width = `${((pI - 3) / 8) * 100}%`;
825
+
826
+ // Calculate extinction coefficient (simplified)
827
+ const extCoeff = calculateExtinctionCoefficient(sequence);
828
+ document.getElementById('ext-coeff-value').textContent = extCoeff.toLocaleString();
829
+
830
+ // Create charts
831
+ createHydrophobicityChart(sequence);
832
+ createSecondaryStructureChart(sequence);
833
+ createDisorderChart(sequence);
834
+ createAccessibilityChart(sequence);
835
+ createTransmembraneChart(sequence);
836
+ }
837
+
838
+ // Function to calculate isoelectric point (simplified)
839
+ function calculateIsoelectricPoint(sequence) {
840
+ // Count charged residues
841
+ let pos = (sequence.match(/[KRH]/g) || []).length;
842
+ let neg = (sequence.match(/[DE]/g) || []).length;
843
+
844
+ // Very simplified pI calculation
845
+ if (pos > neg) return 9.0 + Math.random();
846
+ if (neg > pos) return 5.0 - Math.random();
847
+ return 7.0 + (Math.random() - 0.5);
848
+ }
849
+
850
+ // Function to calculate extinction coefficient (simplified)
851
+ function calculateExtinctionCoefficient(sequence) {
852
+ const trp = (sequence.match(/W/g) || []).length;
853
+ const tyr = (sequence.match(/Y/g) || []).length;
854
+ const cys = (sequence.match(/C/g) || []).length;
855
+
856
+ // Extinction coefficient = (Trp*5500) + (Tyr*1490) + (Cys*125)
857
+ return Math.round(trp * 5500 + tyr * 1490 + cys * 125);
858
+ }
859
+
860
+ // Function to create hydrophobicity chart
861
+ function createHydrophobicityChart(sequence) {
862
+ const ctx = document.getElementById('hydrophobicity-chart').getContext('2d');
863
+
864
+ // Kyte-Doolittle hydrophobicity scale
865
+ const kdScale = {
866
+ 'A': 1.8, 'R': -4.5, 'N': -3.5, 'D': -3.5, 'C': 2.5,
867
+ 'Q': -3.5, 'E': -3.5, 'G': -0.4, 'H': -3.2, 'I': 4.5,
868
+ 'L': 3.8, 'K': -3.9, 'M': 1.9, 'F': 2.8, 'P': -1.6,
869
+ 'S': -0.8, 'T': -0.7, 'W': -0.9, 'Y': -1.3, 'V': 4.2
870
+ };
871
+
872
+ // Calculate hydrophobicity values with window averaging
873
+ const windowSize = 7;
874
+ const hydrophobicity = [];
875
+
876
+ for (let i = 0; i < sequence.length; i++) {
877
+ let sum = 0;
878
+ let count = 0;
879
+
880
+ for (let j = i - Math.floor(windowSize/2); j <= i + Math.floor(windowSize/2); j++) {
881
+ if (j >= 0 && j < sequence.length) {
882
+ sum += kdScale[sequence[j]] || 0;
883
+ count++;
884
+ }
885
+ }
886
+
887
+ hydrophobicity.push(sum / count);
888
+ }
889
+
890
+ // Create chart
891
+ new Chart(ctx, {
892
+ type: 'line',
893
+ data: {
894
+ labels: Array.from({length: sequence.length}, (_, i) => i+1),
895
+ datasets: [{
896
+ label: 'Hydrophobicity',
897
+ data: hydrophobicity,
898
+ borderColor: 'rgb(59, 130, 246)',
899
+ backgroundColor: 'rgba(59, 130, 246, 0.2)',
900
+ borderWidth: 2,
901
+ pointRadius: 0,
902
+ fill: true
903
+ }]
904
+ },
905
+ options: {
906
+ responsive: true,
907
+ maintainAspectRatio: false,
908
+ scales: {
909
+ x: {
910
+ title: {
911
+ display: true,
912
+ text: 'Residue Position'
913
+ }
914
+ },
915
+ y: {
916
+ title: {
917
+ display: true,
918
+ text: 'Hydrophobicity (KD scale)'
919
+ }
920
+ }
921
+ },
922
+ plugins: {
923
+ legend: {
924
+ display: false
925
+ },
926
+ tooltip: {
927
+ callbacks: {
928
+ label: function(context) {
929
+ const pos = context.dataIndex;
930
+ return `Pos ${pos+1}: ${sequence[pos]} (${getAAName(sequence[pos])}) - ${context.parsed.y.toFixed(2)}`;
931
+ }
932
+ }
933
+ }
934
+ }
935
+ }
936
+ });
937
+ }
938
+
939
+ // Function to create secondary structure chart
940
+ function createSecondaryStructureChart(sequence) {
941
+ const ctx = document.getElementById('secondary-structure-chart').getContext('2d');
942
+
943
+ // Generate random secondary structure predictions for demo
944
+ const helix = Array(sequence.length).fill(0).map(() => Math.random() * 0.8);
945
+ const sheet = Array(sequence.length).fill(0).map(() => Math.random() * 0.6);
946
+ const coil = Array(sequence.length).fill(0).map(() => Math.random() * 0.7);
947
+
948
+ // Normalize to sum to 1
949
+ for (let i = 0; i < sequence.length; i++) {
950
+ const total = helix[i] + sheet[i] + coil[i];
951
+ helix[i] = (helix[i] / total) * 100;
952
+ sheet[i] = (sheet[i] / total) * 100;
953
+ coil[i] = (coil[i] / total) * 100;
954
+ }
955
+
956
+ // Create chart
957
+ new Chart(ctx, {
958
+ type: 'bar',
959
+ data: {
960
+ labels: Array.from({length: sequence.length}, (_, i) => i+1),
961
+ datasets: [
962
+ {
963
+ label: 'Helix',
964
+ data: helix,
965
+ backgroundColor: 'rgba(239, 68, 68, 0.7)',
966
+ stack: 'stack'
967
+ },
968
+ {
969
+ label: 'Sheet',
970
+ data: sheet,
971
+ backgroundColor: 'rgba(16, 185, 129, 0.7)',
972
+ stack: 'stack'
973
+ },
974
+ {
975
+ label: 'Coil',
976
+ data: coil,
977
+ backgroundColor: 'rgba(156, 163, 175, 0.7)',
978
+ stack: 'stack'
979
+ }
980
+ ]
981
+ },
982
+ options: {
983
+ responsive: true,
984
+ maintainAspectRatio: false,
985
+ scales: {
986
+ x: {
987
+ title: {
988
+ display: true,
989
+ text: 'Residue Position'
990
+ },
991
+ stacked: true
992
+ },
993
+ y: {
994
+ title: {
995
+ display: true,
996
+ text: 'Probability (%)'
997
+ },
998
+ min: 0,
999
+ max: 100,
1000
+ stacked: true
1001
+ }
1002
+ },
1003
+ plugins: {
1004
+ tooltip: {
1005
+ callbacks: {
1006
+ label: function(context) {
1007
+ const pos = context.dataIndex;
1008
+ const datasetLabel = context.dataset.label || '';
1009
+ const value = context.parsed.y;
1010
+ return `${datasetLabel}: ${value.toFixed(1)}% at pos ${pos+1} (${sequence[pos]})`;
1011
+ }
1012
+ }
1013
+ }
1014
+ }
1015
+ }
1016
+ });
1017
+ }
1018
+
1019
+ // Function to create disorder chart
1020
+ function createDisorderChart(sequence) {
1021
+ const ctx = document.getElementById('disorder-chart').getContext('2d');
1022
+
1023
+ // Generate random disorder predictions for demo
1024
+ const disorder = Array(sequence.length).fill(0).map(() => Math.random());
1025
+
1026
+ // Create chart
1027
+ new Chart(ctx, {
1028
+ type: 'line',
1029
+ data: {
1030
+ labels: Array.from({length: sequence.length}, (_, i) => i+1),
1031
+ datasets: [{
1032
+ label: 'Disorder',
1033
+ data: disorder,
1034
+ borderColor: 'rgb(139, 92, 246)',
1035
+ backgroundColor: 'rgba(139, 92, 246, 0.2)',
1036
+ borderWidth: 2,
1037
+ pointRadius: 0,
1038
+ fill: true
1039
+ }]
1040
+ },
1041
+ options: {
1042
+ responsive: true,
1043
+ maintainAspectRatio: false,
1044
+ scales: {
1045
+ x: {
1046
+ title: {
1047
+ display: true,
1048
+ text: 'Residue Position'
1049
+ }
1050
+ },
1051
+ y: {
1052
+ title: {
1053
+ display: true,
1054
+ text: 'Disorder Probability'
1055
+ },
1056
+ min: 0,
1057
+ max: 1
1058
+ }
1059
+ },
1060
+ plugins: {
1061
+ legend: {
1062
+ display: false
1063
+ },
1064
+ tooltip: {
1065
+ callbacks: {
1066
+ label: function(context) {
1067
+ const pos = context.dataIndex;
1068
+ return `Pos ${pos+1}: ${sequence[pos]} - ${context.parsed.y.toFixed(2)}`;
1069
+ }
1070
+ }
1071
+ }
1072
+ }
1073
+ }
1074
+ });
1075
+ }
1076
+
1077
+ // Function to create accessibility chart
1078
+ function createAccessibilityChart(sequence) {
1079
+ const ctx = document.getElementById('accessibility-chart').getContext('2d');
1080
+
1081
+ // Generate random accessibility predictions for demo
1082
+ const accessibility = Array(sequence.length).fill(0).map(() => Math.random());
1083
+
1084
+ // Create chart
1085
+ new Chart(ctx, {
1086
+ type: 'line',
1087
+ data: {
1088
+ labels: Array.from({length: sequence.length}, (_, i) => i+1),
1089
+ datasets: [{
1090
+ label: 'Relative Solvent Accessibility',
1091
+ data: accessibility,
1092
+ borderColor: 'rgb(20, 184, 166)',
1093
+ backgroundColor: 'rgba(20, 184, 166, 0.2)',
1094
+ borderWidth: 2,
1095
+ pointRadius: 0,
1096
+ fill: true
1097
+ }]
1098
+ },
1099
+ options: {
1100
+ responsive: true,
1101
+ maintainAspectRatio: false,
1102
+ scales: {
1103
+ x: {
1104
+ title: {
1105
+ display: true,
1106
+ text: 'Residue Position'
1107
+ }
1108
+ },
1109
+ y: {
1110
+ title: {
1111
+ display: true,
1112
+ text: 'Relative Accessibility'
1113
+ },
1114
+ min: 0,
1115
+ max: 1
1116
+ }
1117
+ },
1118
+ plugins: {
1119
+ legend: {
1120
+ display: false
1121
+ },
1122
+ tooltip: {
1123
+ callbacks: {
1124
+ label: function(context) {
1125
+ const pos = context.dataIndex;
1126
+ return `Pos ${pos+1}: ${sequence[pos]} - ${context.parsed.y.toFixed(2)}`;
1127
+ }
1128
+ }
1129
+ }
1130
+ }
1131
+ }
1132
+ });
1133
+ }
1134
+
1135
+ // Function to create transmembrane chart
1136
+ function createTransmembraneChart(sequence) {
1137
+ const ctx = document.getElementById('transmembrane-chart').getContext('2d');
1138
+
1139
+ // Generate random transmembrane predictions for demo
1140
+ const tm = Array(sequence.length).fill(0).map(() => Math.random() > 0.9 ? Math.random() * 0.5 + 0.5 : Math.random() * 0.3);
1141
+
1142
+ // Create chart
1143
+ new Chart(ctx, {
1144
+ type: 'line',
1145
+ data: {
1146
+ labels: Array.from({length: sequence.length}, (_, i) => i+1),
1147
+ datasets: [{
1148
+ label: 'Transmembrane Probability',
1149
+ data: tm,
1150
+ borderColor: 'rgb(245, 158, 11)',
1151
+ backgroundColor: 'rgba(245, 158, 11, 0.2)',
1152
+ borderWidth: 2,
1153
+ pointRadius: 0,
1154
+ fill: true
1155
+ }]
1156
+ },
1157
+ options: {
1158
+ responsive: true,
1159
+ maintainAspectRatio: false,
1160
+ scales: {
1161
+ x: {
1162
+ title: {
1163
+ display: true,
1164
+ text: 'Residue Position'
1165
+ }
1166
+ },
1167
+ y: {
1168
+ title: {
1169
+ display: true,
1170
+ text: 'TM Probability'
1171
+ },
1172
+ min: 0,
1173
+ max: 1
1174
+ }
1175
+ },
1176
+ plugins: {
1177
+ legend: {
1178
+ display: false
1179
+ },
1180
+ tooltip: {
1181
+ callbacks: {
1182
+ label: function(context) {
1183
+ const pos = context.dataIndex;
1184
+ return `Pos ${pos+1}: ${sequence[pos]} - ${context.parsed.y.toFixed(2)}`;
1185
+ }
1186
+ }
1187
+ }
1188
+ }
1189
+ }
1190
+ });
1191
+ }
1192
+
1193
+ // Function to create embedding visualization
1194
+ function createEmbeddingChart() {
1195
+ const ctx = document.getElementById('model-embedding-chart').getContext('2d');
1196
+
1197
+ // Generate random 2D embeddings for demo
1198
+ const embeddings = [];
1199
+ const colors = [];
1200
+ const aaClasses = [];
1201
+
1202
+ const sequence = document.getElementById('sequence-input').value.trim().toUpperCase();
1203
+
1204
+ for (let i = 0; i < sequence.length; i++) {
1205
+ const aa = sequence[i];
1206
+ embeddings.push({
1207
+ x: (Math.random() - 0.5) * 10,
1208
+ y: (Math.random() - 0.5) * 10,
1209
+ aa: aa,
1210
+ pos: i+1
1211
+ });
1212
+
1213
+ // Assign colors based on amino acid properties
1214
+ const aaClass = getAAClass(aa);
1215
+ aaClasses.push(aaClass);
1216
+
1217
+ if (aaClass === 'hydrophobic') colors.push('rgba(30, 64, 175, 0.8)');
1218
+ else if (aaClass === 'hydrophilic') colors.push('rgba(22, 101, 52, 0.8)');
1219
+ else if (aaClass === 'acidic') colors.push('rgba(157, 23, 77, 0.8)');
1220
+ else if (aaClass === 'basic') colors.push('rgba(109, 40, 217, 0.8)');
1221
+ else if (aaClass === 'cysteine') colors.push('rgba(133, 77, 14, 0.8)');
1222
+ else if (aaClass === 'proline') colors.push('rgba(14, 116, 144, 0.8)');
1223
+ else colors.push('rgba(113, 63, 18, 0.8)');
1224
+ }
1225
+
1226
+ // Create chart
1227
+ new Chart(ctx, {
1228
+ type: 'scatter',
1229
+ data: {
1230
+ datasets: [{
1231
+ label: 'Amino Acid Embeddings',
1232
+ data: embeddings,
1233
+ backgroundColor: colors,
1234
+ borderColor: 'rgba(0, 0, 0, 0.1)',
1235
+ borderWidth: 1,
1236
+ pointRadius: 5
1237
+ }]
1238
+ },
1239
+ options: {
1240
+ responsive: true,
1241
+ maintainAspectRatio: false,
1242
+ scales: {
1243
+ x: {
1244
+ title: {
1245
+ display: true,
1246
+ text: 'UMAP Dimension 1'
1247
+ }
1248
+ },
1249
+ y: {
1250
+ title: {
1251
+ display: true,
1252
+ text: 'UMAP Dimension 2'
1253
+ }
1254
+ }
1255
+ },
1256
+ plugins: {
1257
+ tooltip: {
1258
+ callbacks: {
1259
+ label: function(context) {
1260
+ const data = context.raw;
1261
+ return `${data.aa} (${getAAName(data.aa)}) at position ${data.pos}`;
1262
+ }
1263
+ }
1264
+ },
1265
+ legend: {
1266
+ display: false
1267
+ }
1268
+ }
1269
+ }
1270
+ });
1271
+ }
1272
+
1273
+ // Initialize with example sequence
1274
+ document.getElementById('example-btn').click();
1275
+ });
1276
+ </script>
1277
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=andersonhuang/plmtools" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1278
+ </html>