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 &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>