cv-curve-fitting / index.html
Rodrigo1421's picture
Update index.html
6f3c7be verified
Raw
History Blame Contribute Delete
15.1 kB
<!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 &amp; 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 &amp; 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 &amp; 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 &amp; 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>