-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathxvg-visualizer.html
More file actions
355 lines (319 loc) · 27.8 KB
/
Copy pathxvg-visualizer.html
File metadata and controls
355 lines (319 loc) · 27.8 KB
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
<!DOCTYPE html>
<html lang="en" class="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XVG & CSV Visualizer | High-Performance Plots | STEMKit</title>
<meta name="title" content="XVG & CSV Visualizer | High-Performance Plots | STEMKit">
<meta name="description" content="Render high-performance WebGL interactive plots for massive GROMACS XVG and CSV log files securely in your browser. 100% secure client-side plotting.">
<meta name="keywords" content="xvg visualizer, gromacs xvg plot, csv plotter, client side data visualization, plot massive csv, webgl scatter plot, scientific data viewer, interactive xvg">
<link rel="canonical" href="https://stemkit.net/xvg-visualizer.html">
<meta property="og:url" content="https://stemkit.net/xvg-visualizer.html">
<meta property="twitter:url" content="https://stemkit.net/xvg-visualizer.html">
<meta property="og:title" content="XVG & CSV Visualizer | High-Performance Plots">
<meta property="twitter:title" content="XVG & CSV Visualizer | High-Performance Plots">
<meta property="og:description" content="Instantly visualize massive GROMACS XVG or CSV data logs directly in your browser. Zero server uploads.">
<meta property="twitter:description" content="Instantly visualize massive GROMACS XVG or CSV data logs directly in your browser. Zero server uploads.">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "STEMKit XVG Visualizer",
"url": "https://stemkit.net/xvg-visualizer.html",
"description": "Render high-performance WebGL interactive plots for massive GROMACS XVG files.",
"applicationCategory": "UtilityApplication",
"operatingSystem": "All",
"browserRequirements": "Requires JavaScript",
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" },
"featureList": [ "Hardware Accelerated Rendering", "GROMACS File Support", "Local Execution", "Zero File Size Limits" ]
}
</script>
<meta name="author" content="STEMKit">
<meta name="theme-color" content="#4f46e5">
<meta property="og:type" content="website">
<meta property="og:image" content="https://stemkit.net/assets/og-image.webp">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:image" content="https://stemkit.net/assets/og-image.webp">
<link rel="icon" type="image/x-icon" href="https://stemkit.net/assets/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="https://stemkit.net/assets/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="https://stemkit.net/assets/favicon-16x16.png">
<link rel="apple-touch-icon" href="https://stemkit.net/assets/apple-touch-icon.png">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/all.min.css">
<script src="js/dependencies/plotly.min.js"></script>
<link rel="stylesheet" href="src/home.css">
<link rel="stylesheet" href="src/output.css">
<link rel="stylesheet" href="src/stemkit-docs.css">
<link rel="stylesheet" href="src/tools/xvg-visualizer.css">
</head>
<body class="bg-slate-50 dark:bg-slate-950 text-slate-900 dark:text-slate-100 min-h-screen flex flex-col font-sans transition-colors duration-300 overflow-x-hidden">
<nav class="sticky top-0 z-50 w-full bg-white/80 dark:bg-slate-950/80 backdrop-blur-md border-b border-slate-200 dark:border-slate-800 transition-colors duration-300">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16 sm:h-20">
<a href="index.html" class="flex items-center gap-2 hover:opacity-80 transition-opacity">
<div class="bg-indigo-600 text-white p-2 sm:p-2.5 rounded-lg shadow-sm flex items-center justify-center">
<i class="fa-solid fa-flask text-lg sm:text-xl"></i>
</div>
<span class="text-xl sm:text-2xl font-black tracking-tighter text-slate-900 dark:text-white">STEMKit</span>
</a>
<div class="hidden md:flex items-center gap-6 text-sm font-semibold text-slate-600 dark:text-slate-300">
<a href="index.html#data-tools" class="hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors">Data</a>
<a href="index.html#comp-tools" class="hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors">Compute</a>
<a href="index.html#pub-tools" class="hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors">Writing & Citations</a>
<a href="index.html#focus-tools" class="hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors">Focus</a>
<div class="h-5 w-px bg-slate-200 dark:bg-slate-700"></div>
<button class="themeToggle p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors" aria-label="Toggle dark mode">
<i class="fa-solid fa-moon dark:hidden text-lg"></i>
<i class="fa-solid fa-sun hidden dark:block text-yellow-400 text-lg"></i>
</button>
<a href="plot-digitizer.html" class="bg-indigo-600 hover:bg-indigo-700 text-white px-5 py-2.5 rounded-full text-sm font-bold transition-all shadow-md hover:shadow-lg">
<i class="fa-solid fa-crosshairs mr-1"></i> Plot Digitizer
</a>
</div>
<div class="flex items-center gap-2 md:hidden">
<button class="themeToggle p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors text-slate-600 dark:text-slate-300">
<i class="fa-solid fa-moon dark:hidden text-lg"></i>
<i class="fa-solid fa-sun hidden dark:block text-yellow-400 text-lg"></i>
</button>
<button id="mobile-menu-btn" class="text-slate-600 dark:text-slate-300 hover:text-indigo-600 p-2 focus:outline-none">
<i class="fa-solid fa-bars text-2xl" id="menu-icon"></i>
</button>
</div>
</div>
</div>
<div id="mobile-menu" class="hidden md:hidden bg-white/95 dark:bg-slate-900/95 backdrop-blur-md border-b border-slate-200 dark:border-slate-800 absolute w-full shadow-xl">
<div class="px-4 pt-2 pb-6 space-y-2 text-base font-semibold text-slate-600 dark:text-slate-300">
<a href="index.html#data-tools" class="mobile-link block py-3 px-4 rounded-xl hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-indigo-600 transition-colors">Data & Stats</a>
<a href="index.html#comp-tools" class="mobile-link block py-3 px-4 rounded-xl hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-indigo-600 transition-colors">Compute</a>
<a href="index.html#pub-tools" class="mobile-link block py-3 px-4 rounded-xl hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-indigo-600 transition-colors">Writing & Citations</a>
<a href="index.html#focus-tools" class="mobile-link block py-3 px-4 rounded-xl hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-indigo-600 transition-colors">Focus & Flow</a>
<div class="pt-4 mt-2 border-t border-slate-100 dark:border-slate-800">
<a href="plot-digitizer.html" class="block text-center bg-indigo-600 hover:bg-indigo-700 text-white py-3 rounded-xl shadow-md transition-colors">Digitizer Pro</a>
</div>
</div>
</div>
</nav>
<main class="stk-shell-tall flex-grow w-full flex flex-col relative">
<section id="uploadZone" class="absolute inset-0 z-10 flex flex-col items-center justify-center p-6 bg-slate-50 dark:bg-slate-950 transition-opacity duration-300">
<div class="w-full max-w-4xl flex flex-col items-center justify-center border-2 border-dashed border-blue-300 dark:border-blue-700 rounded-3xl bg-blue-50/50 dark:bg-blue-900/10 cursor-pointer p-20 text-center group transition-colors hover:bg-blue-50 dark:hover:bg-blue-900/20" id="dropArea">
<input type="file" id="fileInput" accept=".xvg,.csv,.txt,.dat" class="hidden">
<div class="w-24 h-24 bg-blue-100 dark:bg-blue-900/50 rounded-3xl flex items-center justify-center mb-8 text-blue-600 dark:text-blue-400 group-hover:scale-110 transition-transform shadow-sm">
<i class="fa-solid fa-chart-line text-5xl"></i>
</div>
<h1 class="text-4xl font-black mb-4 tracking-tight">Interactive Data Visualizer</h1>
<p class="text-slate-500 dark:text-slate-400 mb-2 max-w-lg leading-relaxed">
Drag and drop massive multi-column data logs. The parser natively ignores GROMACS metadata and renders standard CSVs instantly using WebGL.
</p>
<p class="text-xs font-bold text-slate-400 dark:text-slate-500 mb-8 uppercase tracking-wider">Supported formats: .xvg, .csv, .txt, .dat</p>
<button class="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3.5 rounded-xl font-bold shadow-lg transition-colors flex items-center gap-2">
<i class="fa-solid fa-file-arrow-up"></i> Select Data File
</button>
<button id="loadSampleXvg" class="mt-3 text-sm font-bold text-blue-600 dark:text-blue-400 hover:underline flex items-center gap-1.5"><i class="fa-solid fa-flask-vial"></i> Or load a sample .xvg (GROMACS RMSD)</button>
</div>
</section>
<section id="workspace" class="hidden w-full lg:h-full flex flex-col lg:flex-row p-4 gap-4 pb-12 lg:overflow-hidden overflow-y-auto">
<div class="w-full lg:w-[380px] bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-slate-800 flex flex-col lg:overflow-hidden shadow-sm shrink-0">
<div class="p-5 border-b border-slate-100 dark:border-slate-800 bg-slate-50 dark:bg-slate-950 flex justify-between items-center">
<div>
<h2 class="text-base font-black tracking-tight flex items-center gap-2">
<i class="fa-solid fa-server text-blue-500"></i> Render Engine
</h2>
<p id="fileStats" class="text-[10px] text-slate-500 font-mono mt-1">No file loaded</p>
</div>
<button id="btnCloseWorkspace" class="w-8 h-8 rounded-lg border border-slate-200 dark:border-slate-700 text-slate-400 hover:text-red-500 hover:border-red-200 dark:hover:border-red-800 transition-colors flex items-center justify-center">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="flex-grow overflow-y-auto p-4 custom-scroll space-y-3">
<div class="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden bg-white dark:bg-slate-900">
<div class="px-4 py-3 bg-slate-50 dark:bg-slate-800/50 border-b border-slate-100 dark:border-slate-800 flex justify-between items-center">
<span class="text-xs font-bold text-slate-800 dark:text-slate-200 uppercase tracking-wider">Independent Variable (X)</span>
</div>
<div class="p-3">
<select id="xColSelect" class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-700 rounded-lg p-2 text-xs focus:ring-2 focus:ring-blue-500 outline-none">
</select>
</div>
</div>
<div class="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden bg-white dark:bg-slate-900 flex flex-col max-h-[40vh]">
<div class="px-4 py-3 bg-slate-50 dark:bg-slate-800/50 border-b border-slate-100 dark:border-slate-800 flex justify-between items-center shrink-0">
<span class="text-xs font-bold text-slate-800 dark:text-slate-200 uppercase tracking-wider">Dependent Variables (Y)</span>
<button id="btnToggleAll" class="text-[10px] text-blue-600 hover:text-blue-800 dark:text-blue-400 font-bold uppercase">Toggle All</button>
</div>
<div id="yColContainer" class="p-3 overflow-y-auto custom-scroll flex flex-col gap-2">
</div>
</div>
<div class="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden bg-white dark:bg-slate-900">
<button class="accordion-btn w-full px-4 py-3 bg-slate-50 dark:bg-slate-800/50 flex justify-between items-center text-left focus:outline-none" aria-expanded="false" data-target="settingsContent">
<span class="text-xs font-bold text-slate-800 dark:text-slate-200 uppercase tracking-wider">Optical Parameters</span>
<i class="fa-solid fa-chevron-down accordion-icon text-slate-400 text-xs"></i>
</button>
<div id="settingsContent" class="accordion-content bg-white dark:bg-slate-900 px-4 pb-1">
<div class="py-3 flex flex-col gap-3">
<label class="flex items-center justify-between text-xs font-bold text-slate-600 dark:text-slate-400 cursor-pointer">
Logarithmic Y-Axis
<input type="checkbox" id="plotLogY" class="w-4 h-4 text-blue-600 bg-slate-100 border-slate-300 rounded focus:ring-blue-500">
</label>
<label class="flex items-center justify-between text-xs font-bold text-slate-600 dark:text-slate-400 cursor-pointer">
Show Data Markers
<input type="checkbox" id="plotMarkers" class="w-4 h-4 text-blue-600 bg-slate-100 border-slate-300 rounded focus:ring-blue-500">
</label>
<div>
<div class="flex justify-between text-xs text-slate-500 mb-1 font-bold">
<span>Line Smoothing</span>
</div>
<input type="range" id="plotSmoothing" min="0" max="1.3" step="0.1" value="0" class="w-full accent-blue-600">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-grow bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm flex items-center justify-center overflow-hidden relative h-[65vh] lg:h-full">
<button id="xvgPyBtn" class="absolute top-3 right-3 z-20 px-3 py-1.5 bg-white/90 dark:bg-slate-800/90 border border-slate-200 dark:border-slate-700 rounded-md text-xs font-bold text-slate-600 dark:text-slate-300 hover:text-blue-600 transition-colors shadow-sm backdrop-blur" title="Copy matplotlib code to reproduce this plot"><i class="fa-brands fa-python mr-1"></i> Python</button>
<div id="plotContainer" class="w-full h-full p-2"></div>
<div id="plotLoader" class="absolute inset-0 bg-white/80 dark:bg-slate-900/80 backdrop-blur-sm z-10 hidden flex-col items-center justify-center">
<i class="fa-solid fa-circle-notch fa-spin text-4xl text-blue-600 mb-4"></i>
<p class="text-sm font-bold text-slate-600 dark:text-slate-300">Parsing data array...</p>
</div>
</div>
</section>
</main>
<div class="stk-wrap">
<section class="stk-section" id="how-to-use" aria-label="How to use this tool">
<span class="stk-chip"><i class="fa-solid fa-circle-play"></i> Guide</span>
<h2 class="stk-h2">How to visualize your data</h2>
<p class="stk-lead">Drop a GROMACS <code>.xvg</code> (or any whitespace/CSV numeric table) and explore every column interactively, the parser reads the embedded metadata so your axes and legends come out labelled.</p>
<div class="stk-grid stk-grid-2" style="margin-top:1.5rem;">
<div class="stk-step"><span class="stk-num">1</span><div><h3>Load a file</h3><p>Drag & drop or select a <code>.xvg</code>, <code>.csv</code>, <code>.txt</code> or <code>.dat</code> file, or click <strong>load a sample</strong> to try a synthetic RMSD/Rg trace. Everything is parsed in your browser.</p></div></div>
<div class="stk-step"><span class="stk-num">2</span><div><h3>Pick columns</h3><p>Choose which column is the X axis, then tick any number of Y columns to overlay. Legends and axis titles are pulled from the file's <code>@</code> metadata when present.</p></div></div>
<div class="stk-step"><span class="stk-num">3</span><div><h3>Adjust the view</h3><p>Toggle a log Y axis, show markers, or apply spline smoothing. The plot is fully zoomable and pannable via the Plotly toolbar.</p></div></div>
<div class="stk-step"><span class="stk-num">4</span><div><h3>Export or reproduce</h3><p>Use the camera icon to save a PNG, or click <strong>Python</strong> to copy matplotlib code that redraws the current selection from your file with <code>numpy.loadtxt</code>.</p></div></div>
</div>
</section>
<section class="stk-section" id="how-it-works" aria-label="About the XVG format">
<span class="stk-chip"><i class="fa-solid fa-file-lines"></i> Format</span>
<h2 class="stk-h2">About the GROMACS .xvg format</h2>
<p class="stk-lead">.xvg is the plain-text output written by GROMACS analysis tools (and read by Grace/xmgrace). Knowing its structure explains what this tool does automatically.</p>
<div style="margin-top:1.25rem; display:flex; flex-direction:column; gap:1rem; max-width:52rem;">
<div><h3 class="stk-label">Comment & metadata lines</h3><p class="stk-body">Lines starting with <code>#</code> are comments; lines starting with <code>@</code> are Grace formatting commands. This tool reads <code>@ title</code>, <code>@ xaxis label</code>, <code>@ yaxis label</code> and <code>@ sN legend</code> to label the plot, and skips everything else, so the raw numeric matrix is all that gets plotted.</p></div>
<div><h3 class="stk-label">The data block</h3><p class="stk-body">Below the metadata is a whitespace-separated numeric table: the first column is usually the independent variable (time, distance, reaction coordinate) and each remaining column a data series. Common outputs include RMSD (<code>gmx rms</code>), radius of gyration (<code>gmx gyrate</code>), and PMF/free-energy profiles.</p></div>
<div><h3 class="stk-label">Reproducing in Python</h3><p class="stk-body">The <strong>Python</strong> export uses <code>numpy.loadtxt(..., comments=['@', '#'])</code>, which is the idiomatic way to read an .xvg: the <code>comments</code> argument makes NumPy skip exactly the metadata lines described above, leaving the numeric matrix. The generated script plots only the columns you selected.</p></div>
</div>
</section>
<section class="stk-section" id="references" aria-label="References and documentation">
<span class="stk-chip"><i class="fa-solid fa-book"></i> References</span>
<h2 class="stk-h2">References & documentation</h2>
<ol class="stk-refs-list" style="margin-top:1rem;">
<li>Abraham, M. J., Murtola, T., Schulz, R., et al. (2015). GROMACS: High performance molecular simulations through multi-level parallelism. <em>SoftwareX</em>, 1–2, 19–25. <a href="https://manual.gromacs.org/current/reference-manual/file-formats.html" target="_blank" rel="noopener">GROMACS file formats</a>.</li>
<li>Turner, P. J. (2005). <em>XMGRACE</em> (Grace 5.1). Center for Coastal and Land-Margin Research, OGI. <span style="opacity:.8">(origin of the .xvg/@-command format)</span></li>
<li>Harris, C. R., Millman, K. J., van der Walt, S. J., et al. (2020). Array programming with NumPy. <em>Nature</em>, 585, 357–362. <a href="https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html" target="_blank" rel="noopener">numpy.loadtxt</a>.</li>
<li>Software: <a href="https://plotly.com/javascript/" target="_blank" rel="noopener">Plotly.js</a> (interactive WebGL rendering). Exported code targets <a href="https://matplotlib.org/stable/" target="_blank" rel="noopener">matplotlib</a> + NumPy.</li>
</ol>
</section>
</div>
<footer class="mt-auto border-t border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-950 py-12">
<div class="max-w-7xl mx-auto px-6">
<div class="stk-dir mb-12">
<div>
<h4><i class="fa-solid fa-chart-pie text-indigo-500 text-xs"></i> Data & Stats</h4>
<ul>
<li><a href="plot-digitizer.html">Plot Digitizer</a></li>
<li><a href="data-cleaner.html">Data Cleaner</a></li>
<li><a href="stats-calculator.html">Stat Calculator</a></li>
<li><a href="error-bar-generator.html">Error Bar Gen</a></li>
<li><a href="outlier-detector.html">Outlier Detector</a></li>
<li><a href="curve-fitter.html">Curve Fitter</a></li>
<li><a href="plot-builder.html">Plot Builder</a></li>
<li><a href="xvg-visualizer.html">XVG Visualizer</a></li>
</ul>
</div>
<div>
<h4><i class="fa-solid fa-microchip text-orange-500 text-xs"></i> Compute</h4>
<ul>
<li><a href="structure-inspector.html">3D Inspector</a></li>
<li><a href="coordinate-manipulator.html">Coordinate Manipulator</a></li>
<li><a href="scientific-converter.html">Energy Conversions</a></li>
<li><a href="script-generator.html">HPC Script Gen</a></li>
</ul>
</div>
<div>
<h4><i class="fa-solid fa-book-open text-teal-500 text-xs"></i> Writing & Citations</h4>
<ul>
<li><a href="latex-formatter.html">Equation Formatter</a></li>
<li><a href="latex-tables.html">Visual LaTeX Tables</a></li>
<li><a href="doi-fetcher.html">DOI to BibTeX</a></li>
<li><a href="bibtex-deduplicator.html">BibTeX Deduplicator</a></li>
<li><a href="bibtex-sanitizer.html">BibTeX Sanitizer</a></li>
<li><a href="journal-abbreviator.html">Journal Abbrev</a></li>
</ul>
</div>
<div>
<h4><i class="fa-solid fa-headphones text-fuchsia-500 text-xs"></i> Focus & Flow</h4>
<ul>
<li><a href="pomodoro.html">Ambient Pomodoro</a></li>
<li><a href="decision.html">Decision Matrix</a></li>
<li><a href="sandbox.html">Kinetic Sandbox</a></li>
</ul>
</div>
</div>
<div class="border-t border-slate-200 dark:border-slate-800 pt-8 flex flex-col md:flex-row items-center justify-between text-slate-500 dark:text-slate-400 gap-4">
<div class="flex items-center gap-2">
<i class="fa-solid fa-flask text-xl text-slate-300 dark:text-slate-700"></i>
<span class="font-bold text-slate-700 dark:text-slate-300">STEMKit</span>
</div>
<div class="text-center text-sm font-medium">© 2026 STEMKit. Built by <a href="https://github.com/LD-Shell" target="_blank" rel="noopener" class="font-semibold hover:text-indigo-500 transition-colors">Olanrewaju M. Daramola</a>.</div>
<div class="flex gap-6 text-sm font-medium">
<a href="privacy.html#privacy" class="hover:text-indigo-500 transition-colors">Privacy Policy</a>
<a href="privacy.html#terms" class="hover:text-indigo-500 transition-colors">Terms of Service</a>
</div>
</div>
</div>
</footer>
<script>
// 1. Theme toggle logic (Mobile & Desktop)
document.querySelectorAll('.themeToggle').forEach(btn => {
btn.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
});
});
// 2. Mobile menu logic
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
const mobileMenu = document.getElementById('mobile-menu');
const menuIcon = document.getElementById('menu-icon');
if(mobileMenuBtn) {
mobileMenuBtn.addEventListener('click', () => {
mobileMenu.classList.toggle('hidden');
if(mobileMenu.classList.contains('hidden')) {
menuIcon.classList.remove('fa-xmark');
menuIcon.classList.add('fa-bars');
} else {
menuIcon.classList.remove('fa-bars');
menuIcon.classList.add('fa-xmark');
}
});
document.querySelectorAll('.mobile-link').forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.add('hidden');
menuIcon.classList.remove('fa-xmark');
menuIcon.classList.add('fa-bars');
});
});
}
</script>
<script type="module" src="js/xvg-visualizer.js"></script> <!-- Python code modal -->
<div id="xvgCodeModal" class="fixed inset-0 z-[60] hidden items-center justify-center p-4" style="background:rgba(15,23,42,.6);">
<div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-2xl shadow-2xl w-full max-w-2xl max-h-[85vh] flex flex-col">
<div class="flex items-center justify-between p-4 border-b border-slate-200 dark:border-slate-700">
<h3 class="font-bold text-slate-800 dark:text-slate-100 flex items-center gap-2"><i class="fa-brands fa-python text-blue-500"></i> matplotlib code</h3>
<div class="flex items-center gap-2">
<button id="xvgCopyCode" class="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 text-white rounded-md text-xs font-bold transition-colors"><i class="fa-solid fa-copy mr-1"></i> Copy</button>
<button id="xvgCloseCode" class="w-8 h-8 rounded-md text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors"><i class="fa-solid fa-xmark"></i></button>
</div>
</div>
<div class="p-1 overflow-auto"><pre id="xvgCodeBlock" class="text-xs leading-relaxed p-4 font-mono text-slate-800 dark:text-slate-200 whitespace-pre overflow-x-auto"></pre></div>
<div class="px-4 py-2.5 border-t border-slate-200 dark:border-slate-700 text-[11px] text-slate-500 dark:text-slate-400">Reproduces the current plot from your .xvg with <code>numpy.loadtxt</code> + <code>matplotlib</code>. Point the path at your file.</div>
</div>
</div>
</body>
</html>