-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
228 lines (211 loc) · 12.3 KB
/
index.html
File metadata and controls
228 lines (211 loc) · 12.3 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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>YSI Processor Live</title>
<meta name="description" content="Browser-based YSI 2950 BioSample processor for replicate QC, means, standard deviation, and export-ready results.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/styles.css">
</head>
<body>
<header class="hc-header">
<div class="hc-header-brand">
<div class="hc-logo" aria-hidden="true">
<span class="hc-logo-glyph">YSI</span>
</div>
<div class="hc-header-text">
<div class="hc-title-line">
<h1>YSI Processor Live</h1>
<p class="hc-tagline">QC y análisis de réplicas para YSI 2950 BioSample</p>
</div>
</div>
</div>
<div class="hc-header-right">
<a class="hc-suite-pill" href="https://www.hostcell.app" target="_blank" rel="noopener noreferrer">
<span class="hc-suite-label">HostCell Lab Suite</span>
</a>
</div>
</header>
<div class="page-shell">
<main class="main-grid">
<!-- ── Intake + settings ── -->
<section class="panel intake-panel" aria-label="File upload and settings">
<!-- Settings bar: horizontal, above the dropzone -->
<div class="settings-bar">
<span class="settings-label">QC Thresholds</span>
<div class="settings-bar-fields">
<label class="setting-field">
<span>CV (%)</span>
<input id="cv-threshold" type="number" min="0" step="0.1" value="5.0">
</label>
<label class="setting-field">
<span>Modified z</span>
<input id="modz-threshold" type="number" min="0" step="0.1" value="3.5">
</label>
<label class="setting-field">
<span>IQR multiplier</span>
<input id="iqr-multiplier" type="number" min="0" step="0.1" value="1.5">
</label>
<label class="setting-field">
<span>Consensus signals</span>
<input id="consensus-flags" type="number" min="1" step="1" value="1">
</label>
</div>
<div class="settings-bar-actions">
<button id="process-button" class="btn-primary">
<svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM9.555 7.168A1 1 0 0 0 8 8v4a1 1 0 0 0 1.555.832l3-2a1 1 0 0 0 0-1.664l-3-2Z" clip-rule="evenodd"/></svg>
Process Files
</button>
<button id="load-demo-button" class="btn-ghost">Format guide</button>
</div>
</div>
<!-- Dropzone + info columns -->
<div class="intake-body">
<div class="intake-drop-side">
<label class="dropzone" id="dropzone">
<input id="file-input" type="file" accept=".csv,text/csv" multiple aria-label="Choose CSV files">
<svg class="drop-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 16V4m0 0L8 8m4-4 4 4"/><rect x="3" y="16" width="18" height="5" rx="2"/>
</svg>
<span class="drop-title">Drop BioSample CSV files here</span>
<span class="drop-subtitle">or click to choose one or more files</span>
</label>
<div class="file-list" id="file-list"></div>
<div class="status-bar" id="status-box">Waiting for BioSample files.</div>
</div>
<div class="intake-info-side">
<div>
<p class="settings-label">Required CSV columns</p>
<div class="pill-grid" style="margin-top:0.4rem;">
<span class="pill">PlateSequenceName</span>
<span class="pill">BatchName</span>
<span class="pill">WellId</span>
<span class="pill">ChemistryId</span>
<span class="pill">Concentration</span>
</div>
<p class="settings-note" style="margin-top:0.5rem;">
Optional: <code>CompletionState</code>, <code>Units</code>, <code>LocalCompletionTime</code>, <code>Errors</code>
</p>
</div>
<details class="method-accordion">
<summary>How are outliers detected?</summary>
<div class="method-body">
<p>Three independent statistical tests run on each replicate group (≥ 3 replicates required). A replicate is recommended for discard when it accumulates enough flags (configurable via <em>Consensus signals</em>).</p>
<dl>
<dt>Modified Z-Score</dt>
<dd>Uses the median and MAD — robust to non-normal distributions. Flags a replicate if |0.6745 × (value − median) / MAD| exceeds the threshold.</dd>
<dt>IQR Fence</dt>
<dd>Flags values outside Q1 − multiplier × IQR or Q3 + multiplier × IQR.</dd>
<dt>Leave-One-Out CV</dt>
<dd>Tests whether removing each replicate reduces group CV below threshold. Only the best-improvement replicate is a candidate.</dd>
</dl>
<p>The <strong>cleaned mean/SD</strong> is computed after the recommended discard. Groups are <strong>REVIEW</strong> when no single outlier is found but CV still exceeds threshold.</p>
</div>
</details>
<div class="manifest-preview" id="manifest-preview"></div>
</div>
</div>
</section>
<!-- ── KPI strip ── -->
<section class="panel kpi-panel hidden" id="kpi-panel" aria-label="Run summary">
<div class="kpi-grid" id="kpi-grid"></div>
</section>
<!-- ── Results table ── -->
<section class="panel results-panel hidden" id="quick-results-panel" aria-label="Cleaned results">
<div class="panel-head">
<div class="panel-head-left">
<h2>Results</h2>
<p>Cleaned mean ± SD per well. Flagged wells appear first.</p>
</div>
<div class="panel-head-actions">
<button id="copy-results-btn" class="btn-secondary">
<svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M7 3.5A1.5 1.5 0 0 1 8.5 2h3.879a1.5 1.5 0 0 1 1.06.44l3.122 3.12A1.5 1.5 0 0 1 17 6.622V12.5a1.5 1.5 0 0 1-1.5 1.5h-1v-3.379a3 3 0 0 0-.879-2.121L10.5 5.379A3 3 0 0 0 8.379 4.5H7v-1Z"/><path d="M4.5 6A1.5 1.5 0 0 0 3 7.5v9A1.5 1.5 0 0 0 4.5 18h7a1.5 1.5 0 0 0 1.5-1.5v-5.879a1.5 1.5 0 0 0-.44-1.06L9.44 6.439A1.5 1.5 0 0 0 8.378 6H4.5Z"/></svg>
Copy for Excel
</button>
</div>
</div>
<div class="downloads-strip">
<span class="downloads-label">Download</span>
<button id="download-summary" class="dl-btn">
<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 .5a.5.5 0 0 1 .5.5v7.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 8.793V1a.5.5 0 0 1 .5-.5Zm-5 11a.5.5 0 0 0 0 1h10a.5.5 0 0 0 0-1H3Z"/></svg>
Summary
</button>
<button id="download-measurements" class="dl-btn">
<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 .5a.5.5 0 0 1 .5.5v7.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 8.793V1a.5.5 0 0 1 .5-.5Zm-5 11a.5.5 0 0 0 0 1h10a.5.5 0 0 0 0-1H3Z"/></svg>
Measurements
</button>
<button id="download-outliers" class="dl-btn">
<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 .5a.5.5 0 0 1 .5.5v7.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 8.793V1a.5.5 0 0 1 .5-.5Zm-5 11a.5.5 0 0 0 0 1h10a.5.5 0 0 0 0-1H3Z"/></svg>
Outliers
</button>
<button id="download-manifest" class="dl-btn">
<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 .5a.5.5 0 0 1 .5.5v7.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 8.793V1a.5.5 0 0 1 .5-.5Zm-5 11a.5.5 0 0 0 0 1h10a.5.5 0 0 0 0-1H3Z"/></svg>
Manifest
</button>
</div>
<div class="table-wrap">
<table id="quick-results-table"></table>
</div>
</section>
<!-- ── CV chart ── -->
<section class="panel chart-panel hidden" id="chart-panel" aria-label="Variability snapshot">
<div class="panel-head">
<div class="panel-head-left">
<h2>Variability Snapshot</h2>
<p>Top wells by raw CV with cleaned CV after recommended discard.</p>
</div>
<div class="chart-legend">
<span class="legend-raw">Raw CV</span>
<span class="legend-clean">Cleaned CV</span>
<span class="legend-threshold">Threshold</span>
</div>
</div>
<div id="cv-chart" class="chart-wrap"></div>
</section>
<!-- ── Flagged replicates ── -->
<section class="panel flags-panel hidden" id="flags-panel" aria-label="Flagged replicates">
<div class="panel-head">
<div class="panel-head-left">
<h2>Flagged Replicates</h2>
<p>Individual replicates that triggered review or are recommended for discard.</p>
</div>
</div>
<div class="table-wrap">
<table id="outliers-table"></table>
</div>
</section>
<!-- ── Annotated measurements (collapsed tab) ── -->
<details class="measurements-details hidden" id="measurements-details">
<summary class="measurements-summary">
<svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M6 4.75A.75.75 0 0 1 6.75 4h10.5a.75.75 0 0 1 0 1.5H6.75A.75.75 0 0 1 6 4.75ZM6 10a.75.75 0 0 1 .75-.75h10.5a.75.75 0 0 1 0 1.5H6.75A.75.75 0 0 1 6 10Zm0 5.25a.75.75 0 0 1 .75-.75h10.5a.75.75 0 0 1 0 1.5H6.75a.75.75 0 0 1-.75-.75ZM1.99 4.75a1 1 0 0 1 1-1H3a1 1 0 0 1 0 2h-.01a1 1 0 0 1-1-1ZM1.99 10a1 1 0 0 1 1-1H3a1 1 0 0 1 0 2h-.01a1 1 0 0 1-1-1ZM1.99 15.25a1 1 0 0 1 1-1H3a1 1 0 0 1 0 2h-.01a1 1 0 0 1-1-1Z" clip-rule="evenodd"/></svg>
<span>Annotated Measurements</span>
<span class="measurements-desc">Replicate-level QC detail for downstream audit</span>
<span class="measurements-chevron">▸</span>
</summary>
<div class="measurements-body">
<div class="table-wrap">
<table id="measurements-table"></table>
</div>
</div>
</details>
</main>
</div>
<footer class="hc-footer">
<div class="hc-footer-inner">
<div class="hc-footer-suite">
<span class="hc-footer-name">HostCell Lab Suite</span>
<span class="hc-footer-slogan">Practical tools for high-performance biotechnology</span>
</div>
<span class="hc-footer-author">© Emiliano Balderas Ramírez</span>
<a href="https://github.com/ebalderasr/ysi-processor" class="hc-footer-github" target="_blank" rel="noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="currentColor" aria-label="GitHub"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2Z"/></svg>
Ver en GitHub
</a>
</div>
</footer>
<script src="assets/app.js"></script>
</body>
</html>