Spaces:
Running on Zero
Running on Zero
File size: 15,081 Bytes
b49b2a8 9fa9b8c b49b2a8 6f3c7be b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 4cfad8a 9fa9b8c 6f3c7be 9fa9b8c 6f3c7be 9fa9b8c b49b2a8 9fa9b8c b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 9fa9b8c b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 9fa9b8c 6f3c7be b49b2a8 6f3c7be b49b2a8 9fa9b8c 6f3c7be b49b2a8 9fa9b8c 6f3c7be b49b2a8 6f3c7be b49b2a8 4cfad8a 6f3c7be b49b2a8 9fa9b8c b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 9fa9b8c b49b2a8 6f3c7be 9fa9b8c 6f3c7be 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 6f3c7be 9fa9b8c b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 6f3c7be b49b2a8 9fa9b8c b49b2a8 6f3c7be b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c b49b2a8 9fa9b8c 4cfad8a b49b2a8 4cfad8a | 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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cyclic Voltammetry Parameter Extraction & Physical Model Fitting</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.plot.ly/plotly-2.27.0.min.js" charset="utf-8"></script>
</head>
<body>
<!-- Top Academic Navigation Bar -->
<nav class="top-nav">
<div class="nav-container">
<div class="nav-brand">
<span class="brand-title">Cyclic Voltammetry Analysis</span>
<span class="brand-subtitle">Physical Model & Non-Linear JAX Parameter Extraction</span>
</div>
<div class="nav-links">
<div class="engine-badge" id="engine-status-badge">
<span class="status-dot online" id="engine-dot"></span>
<span class="engine-text" id="engine-label">JAX Optimization Engine Ready</span>
</div>
</div>
</div>
</nav>
<!-- Main Fluid Layout Container -->
<main class="app-container">
<div class="content-grid">
<!-- Left Sidebar: Parameters & Data Configuration -->
<aside class="controls-column">
<section class="panel control-panel">
<header class="panel-header">
<h2>Experiment Configuration</h2>
</header>
<div class="panel-body">
<form id="cv-form" onsubmit="window.handleFormSubmit && window.handleFormSubmit(event);">
<!-- File Upload Area -->
<div class="file-upload-wrapper" id="drop-zone"
ondragover="event.preventDefault(); this.classList.add('dragover');"
ondragleave="this.classList.remove('dragover');"
ondrop="event.preventDefault(); this.classList.remove('dragover'); window.handleCSVDrop && window.handleCSVDrop(event);">
<label class="section-label">Voltammetry Data File (.csv)</label>
<div class="file-upload-box" onclick="document.getElementById('csv-file-input').click();">
<div class="file-icon">📄</div>
<span class="btn-file-select">Choose CSV Data</span>
<span class="drag-hint">or drop file here</span>
</div>
<div class="file-status-row">
<span id="file-name-display">No file selected</span>
</div>
<input type="file" id="csv-file-input" class="hidden-file-input" accept=".csv,.txt,.dat" onchange="window.handleCSVFileChange && window.handleCSVFileChange(this);" />
</div>
<!-- Generalized 2-Column Selectors -->
<fieldset class="form-section">
<legend>Data Columns</legend>
<div class="input-grid">
<div class="form-group">
<label for="pot_col">Potential (<i>V</i>) Column</label>
<select id="pot_col" name="pot_col" class="academic-dropdown" onchange="window.updateLivePreviewFromColumns && window.updateLivePreviewFromColumns();">
<option value="0">Column 0</option>
</select>
</div>
<div class="form-group">
<label for="cur_col">Current (<i>I</i>) Column</label>
<select id="cur_col" name="cur_col" class="academic-dropdown" onchange="window.updateLivePreviewFromColumns && window.updateLivePreviewFromColumns();">
<option value="1">Column 1</option>
</select>
</div>
</div>
<div class="column-meta-bar" id="column-meta-bar">
<span id="detected-columns-text">Upload a file to map columns</span>
</div>
<!-- Live Data Stats Preview -->
<div class="col-stats-preview" id="col-stats-preview">
<div class="stat-pill">
<span class="stat-k">V Range:</span>
<span class="stat-v" id="stat-v-range">-</span>
</div>
<div class="stat-pill">
<span class="stat-k">I Range:</span>
<span class="stat-v" id="stat-i-range">-</span>
</div>
<div class="stat-pill">
<span class="stat-k">Data Points:</span>
<span class="stat-v" id="stat-points-count">-</span>
</div>
</div>
</fieldset>
<!-- Physical & Experimental Parameters -->
<fieldset class="form-section">
<legend>Physical & Electrochemical Parameters</legend>
<div class="input-grid">
<div class="form-group">
<label for="scan_rate">Scan Rate <i>v</i> (V/s)</label>
<input type="number" step="any" id="scan_rate" name="scan_rate" value="0.010" required />
</div>
<div class="form-group">
<label for="film_thickness">Film Thickness <i>L</i> (cm)</label>
<input type="number" step="any" id="film_thickness" name="film_thickness" value="0.0001" required />
</div>
</div>
<div class="input-grid" style="margin-top: 0.65rem;">
<div class="form-group">
<label for="v_min">Potential Range <i>V</i><sub>min</sub> (V)</label>
<input type="number" step="any" id="v_min" name="v_min" value="-1.0" required />
</div>
<div class="form-group">
<label for="v_max">Potential Range <i>V</i><sub>max</sub> (V)</label>
<input type="number" step="any" id="v_max" name="v_max" value="1.0" required />
</div>
</div>
</fieldset>
<!-- Advanced Computational Hyperparameters (Collapsible) -->
<div class="advanced-section">
<button type="button" class="advanced-toggle" id="advanced-toggle" onclick="window.toggleAdvanced && window.toggleAdvanced();" aria-expanded="false">
<span>Solver Hyperparameters & JAX Grid</span>
<span class="toggle-icon" id="toggle-icon">▼</span>
</button>
<div class="advanced-content hidden" id="advanced-content">
<fieldset class="form-section sub-section">
<div class="input-grid">
<div class="form-group">
<label for="num_peaks">DOS Sub-Bands (<i>N</i>)</label>
<input type="number" id="num_peaks" name="num_peaks" value="50" min="5" max="200" />
</div>
<div class="form-group">
<label for="num_terms">Fourier PDE Terms</label>
<input type="number" id="num_terms" name="num_terms" value="50" min="10" max="200" />
</div>
<div class="form-group">
<label for="skip_factor">Downsample Factor</label>
<input type="number" id="skip_factor" name="skip_factor" value="5" min="1" max="50" />
</div>
<div class="form-group">
<label for="max_iter">L-BFGS-B Iterations</label>
<input type="number" id="max_iter" name="max_iter" value="100" min="10" max="500" />
</div>
<div class="form-group">
<label for="tol_ftol">Tolerance (<i>f_tol</i>)</label>
<input type="number" step="any" id="tol_ftol" name="tol_ftol" value="1e-8" />
</div>
<div class="form-group">
<label for="loss_weight_const">Weight Constant</label>
<input type="number" step="any" id="loss_weight_const" name="loss_weight_const" value="1.0" />
</div>
</div>
</fieldset>
</div>
</div>
<!-- Execution Button -->
<button type="submit" id="submit-btn" class="btn-primary">
Execute Optimization
</button>
</form>
</div>
</section>
</aside>
<!-- Right Main Area: Primary Plots & Diagnostics -->
<section class="visualizations-column">
<!-- Status & Primary Voltammogram Canvas -->
<div class="panel main-chart-panel">
<header class="panel-header status-header-row">
<div class="status-left">
<div class="spinner hidden" id="status-spinner"></div>
<div>
<h2 id="status-stage">System Ready</h2>
<p id="status-details">Upload experimental voltammogram CSV data to begin parameter extraction.</p>
</div>
</div>
</header>
<div class="panel-body chart-panel-body">
<div class="chart-wrapper-large">
<div id="live-chart"></div>
</div>
</div>
</div>
<!-- Extracted Parameters & Derived Spectra -->
<div id="results-panel" class="results-container hidden">
<!-- Physical Constants & Optimization Summary -->
<div class="panel">
<header class="panel-header results-header-row">
<h3>Extracted Physical Parameters</h3>
<div class="export-actions">
<button type="button" class="btn-export" onclick="window.exportResultsJson && window.exportResultsJson();">
Export JSON
</button>
<button type="button" class="btn-export" onclick="window.exportResultsCsv && window.exportResultsCsv();">
Export CSV Curves
</button>
</div>
</header>
<div class="panel-body">
<div class="stats-grid" id="params-output"></div>
</div>
</div>
<!-- Secondary Physical Diagnostics: DOS(V) & D(V) -->
<div class="secondary-charts-grid">
<div class="panel">
<header class="panel-header">
<h3>Density of States DOS(V)</h3>
</header>
<div class="panel-body chart-panel-body">
<div class="chart-wrapper-diagnostic">
<div id="dos-chart"></div>
</div>
</div>
</div>
<div class="panel">
<header class="panel-header">
<h3>Diffusivity Profile D(V)</h3>
</header>
<div class="panel-body chart-panel-body">
<div class="chart-wrapper-diagnostic">
<div id="diffusivity-chart"></div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</main>
<!-- Bootstrap Trigger to ensure JS runs regardless of iframe or innerHTML injection -->
<img src="data:image/svg+xml;utf8,<svg/>" style="display:none" onload="window.__initCVApp && window.__initCVApp();" onerror="window.__initCVApp && window.__initCVApp();" />
<script src="app.js"></script>
</body>
</html> |