-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfindings.html
More file actions
387 lines (360 loc) · 27.2 KB
/
Copy pathfindings.html
File metadata and controls
387 lines (360 loc) · 27.2 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
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Findings · Preprint to Publication</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Newsreader:opsz,wght@6..72,400;6..72,500;6..72,600&display=swap');
:root{
--ink:#16202e; --muted:#5b6b7e; --line:#e6eaf0; --bg:#f6f8fb; --card:#fff;
--blue:#1e3a8a; --blue2:#2563eb; --sky:#e8f0fe; --coral:#ff6b6b;
--unchanged:#1f9d61; --minor:#e0a516; --major:#d6455d;
--cautious:#2f6fb0; --confident:#c9711a; --shadow:0 1px 3px rgba(20,40,80,.05),0 10px 30px rgba(20,40,80,.06);
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;color:var(--ink);background:var(--bg);line-height:1.6;-webkit-font-smoothing:antialiased}
a{color:var(--blue2);text-decoration:none}a:hover{text-decoration:underline}
nav.top{display:flex;justify-content:space-between;align-items:center;padding:16px 32px;background:#fff;border-bottom:1px solid var(--line);position:sticky;top:0;z-index:50}
nav.top .brand{font-size:17px;font-weight:800;color:var(--blue);display:flex;align-items:center;gap:9px;letter-spacing:-.01em}
nav.top .brand .dot{width:11px;height:11px;border-radius:50%;background:linear-gradient(135deg,var(--coral),var(--blue));box-shadow:0 0 0 4px rgba(30,58,138,.08)}
nav.top .links{display:flex;gap:6px}
nav.top .links a{color:var(--muted);font-size:14px;font-weight:600;padding:7px 13px;border-radius:8px;transition:.15s}
nav.top .links a:hover{color:var(--blue);background:var(--sky);text-decoration:none}
nav.top .links a.active{color:var(--blue);background:var(--sky)}
.hero{background:linear-gradient(140deg,#0f1f3d 0%,#1e3a8a 55%,#2c54b6 100%);color:#fff;padding:52px 24px 46px;text-align:center}
.hero h1{font-size:30px;font-weight:800;letter-spacing:-.02em;max-width:820px;margin:0 auto 12px;line-height:1.25}
.hero p{font-size:16px;opacity:.9;max-width:680px;margin:0 auto;font-weight:300}
.hero .by{margin-top:16px;font-size:13px;opacity:.7}
.wrap{max-width:1080px;margin:0 auto;padding:0 24px 80px}
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:-32px auto 8px;position:relative;z-index:5}
@media(max-width:760px){.kpis{grid-template-columns:repeat(2,1fr)}}
.kpi{background:#fff;border:1px solid var(--line);border-radius:14px;padding:18px 16px;text-align:center;box-shadow:var(--shadow)}
.kpi .v{font-size:26px;font-weight:800;color:var(--blue);letter-spacing:-.02em;line-height:1}
.kpi .l{font-size:11.5px;color:var(--muted);margin-top:7px;font-weight:600;line-height:1.4}
section.block{background:#fff;border:1px solid var(--line);border-radius:18px;padding:30px 32px;margin-top:24px;box-shadow:var(--shadow)}
.eyebrow{font-size:11.5px;font-weight:800;text-transform:uppercase;letter-spacing:.09em;color:var(--coral);margin-bottom:7px}
section.block h2{font-size:22px;font-weight:800;letter-spacing:-.01em;margin-bottom:8px}
section.block .lead{font-size:15px;color:var(--muted);max-width:760px;margin-bottom:6px}
section.block .lead b{color:var(--ink)}
.note{font-size:12.5px;color:#8593a4;margin-top:14px;border-top:1px dotted var(--line);padding-top:11px}
.figrow{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:22px}
@media(max-width:760px){.figrow{grid-template-columns:1fr}}
.fig{min-width:0}
.fig .cap{font-size:12.5px;color:var(--muted);text-align:center;margin-top:10px;line-height:1.5}
.fig .cap b{color:var(--ink)}
.panel-h{font-size:13px;font-weight:700;color:var(--blue);text-align:center;margin-bottom:10px}
.canvas-box{position:relative;height:300px}
.canvas-box.tall{height:360px}
/* big stat callout */
.callout{display:flex;flex-wrap:wrap;gap:14px;margin-top:22px}
.callout .c{flex:1;min-width:150px;background:var(--bg);border:1px solid var(--line);border-radius:13px;padding:16px 18px}
.callout .c .n{font-size:23px;font-weight:800;letter-spacing:-.01em}
.callout .c .n.g{color:var(--unchanged)} .callout .c .n.a{color:var(--minor)} .callout .c .n.r{color:var(--major)} .callout .c .n.b{color:var(--blue)}
.callout .c .t{font-size:12.5px;color:var(--muted);margin-top:4px;line-height:1.45}
/* alluvial / transitions */
.alluvial{width:100%;height:auto}
/* heatmap */
.heat{display:grid;grid-template-columns:auto repeat(3,1fr);gap:5px;max-width:520px;margin:8px auto 0}
.heat .hcell{padding:13px 8px;border-radius:8px;text-align:center;font-size:13px;font-weight:700}
.heat .hhdr{font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;display:flex;align-items:center;justify-content:center;padding:6px}
.heat .hrow{font-size:11.5px;font-weight:700;color:var(--ink);display:flex;align-items:center;padding-right:6px}
.retract-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:center;margin-top:8px}
@media(max-width:640px){.retract-grid{grid-template-columns:1fr}}
.footer{text-align:center;color:var(--muted);font-size:13px;padding:36px 20px 0}
.pill-row{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:14px}
.pill{font-size:12.5px;font-weight:600;background:var(--sky);color:var(--blue);padding:6px 13px;border-radius:20px}
#boot{max-width:1080px;margin:30px auto;padding:0 24px;color:var(--muted)}
</style>
</head>
<body>
<nav class="top">
<div class="links">
<a href="index.html">Overview</a>
<a href="findings.html" class="active">Findings</a>
<a href="browser.html">Browse data</a>
</div>
</nav>
<div class="hero">
<h1>Peer review leaves the central claims of most biomedical preprints intact</h1>
<p>A claim-level comparison of 72,644 bioRxiv preprints with their peer-reviewed publications, labelled by a large language model.</p>
<div class="by">Hao Yin, Woosung Anh, Patrycja M. Forster & Ruslan Rust · Claude Sonnet 4.6</div>
</div>
<div class="wrap">
<div class="kpis" id="kpis"></div>
<div id="boot">Loading figures…</div>
<div id="content" style="display:none">
<!-- HEADLINE -->
<section class="block">
<div class="eyebrow">The headline · Figure 1a–b</div>
<h2>Most primary claims survive peer review</h2>
<p class="lead">For every pair, the model extracted the single <b>primary claim</b> of the abstract and judged whether it was unchanged, minorly revised, or majorly changed between the preprint and the published version. The large majority changed little.</p>
<div class="callout">
<div class="c"><div class="n g" id="k-unch">–</div><div class="t">Primary claim <b>unchanged</b></div></div>
<div class="c"><div class="n a" id="k-min">–</div><div class="t"><b>Minor</b> revision (wording only)</div></div>
<div class="c"><div class="n r" id="k-maj">–</div><div class="t"><b>Major</b> change in content</div></div>
<div class="c"><div class="n b" id="k-ratio">–</div><div class="t">More cautious vs more confident wording</div></div>
</div>
<div class="figrow">
<div class="fig"><div class="panel-h">a · Content change of the primary claim</div><div class="canvas-box"><canvas id="c_1a"></canvas></div>
<div class="cap"><b>89.9%</b> of primary claims were unchanged or only minorly revised; just <b>10.2%</b> changed substantially.</div></div>
<div class="fig"><div class="panel-h">b · Hedging shift of the primary claim</div><div class="canvas-box"><canvas id="c_1b"></canvas></div>
<div class="cap">When wording shifted, it moved toward caution <b>twice as often</b> as toward confidence (8.4% vs 4.2%).</div></div>
</div>
</section>
<!-- CAUTION SCALES -->
<section class="block">
<div class="eyebrow">Caution scales with revision · Figure 1c</div>
<h2>The bigger the revision, the more the wording softens</h2>
<p class="lead">Among <b>majorly revised</b> claims, the wording became more cautious in 38.5% and more confident in only 19.8% of assessable cases. Claims labelled unchanged in content carry no hedging shift by definition, so the comparison runs between the minor and major strata.</p>
<div class="figrow">
<div class="fig"><div class="panel-h">c · Hedging direction within each content-change stratum</div><div class="canvas-box"><canvas id="c_1c"></canvas></div>
<div class="cap">Percent of claims with an assessable hedging label that became more cautious (blue) or more confident (orange).</div></div>
<div class="fig" style="display:flex;flex-direction:column;justify-content:center">
<div class="callout" style="margin-top:0;flex-direction:column">
<div class="c"><div class="n b">2:1</div><div class="t">Across the whole corpus, weakened claims outnumber strengthened claims roughly two to one — a ratio below parity in <b>every</b> field.</div></div>
<div class="c"><div class="n r">P<0.001</div><div class="t">Two-sided sign test on the 9,150 pairs with any hedging shift.</div></div>
</div>
</div>
</div>
</section>
<!-- BY FIELD -->
<section class="block">
<div class="eyebrow">By field · Figure 1d–e</div>
<h2>Revision rate varies by field, but the direction of caution does not</h2>
<p class="lead">Major revision of the primary claim ranged from <b>7.2% in bioinformatics</b> to <b>17.5% in microbiology</b> across the 17 fields with at least 1,500 pairs. Yet the shift toward caution held everywhere: the strengthened-to-weakened ratio stayed below one in every field.</p>
<div class="fig" style="margin-top:20px"><div class="panel-h">d · Content-change composition by field (ordered by major-revision rate)</div><div class="canvas-box tall"><canvas id="c_1d"></canvas></div></div>
<div class="fig" style="margin-top:26px"><div class="panel-h">e · Strengthened-to-weakened ratio of primary claims by field (dashed line = parity)</div><div class="canvas-box"><canvas id="c_1e"></canvas></div></div>
</section>
<!-- TYPE -->
<section class="block">
<div class="eyebrow">Claim types · Figure 1f</div>
<h2>The kind of claim almost never changes</h2>
<p class="lead">Among the 71,055 pairs whose primary claim was present on both sides and carried a valid type, the claim type was preserved in <b>97.7%</b>. Among the 1,605 that did change type, transitions ran mostly between adjacent categories — for example mechanistic to descriptive or associative — rather than collapsing to a null result.</p>
<div class="fig" style="margin-top:16px"><div class="panel-h">f · Primary claim-type transitions among pairs whose type changed</div>
<svg id="alluvial" class="alluvial" viewBox="0 0 720 420" preserveAspectRatio="xMidYMid meet"></svg>
<div class="cap">Band width is proportional to the number of pairs. <b>Descriptive</b> claims show the largest net gain; <b>mechanistic</b> claims are the most often reclassified.</div></div>
</section>
<!-- DRIVERS -->
<section class="block">
<div class="eyebrow">Drivers of revision · Figure 2</div>
<h2>Larger revisions track longer review and higher-impact journals</h2>
<p class="lead">Revision moves the claims of an abstract together, declines year on year, and rises with both the length of peer review and the impact of the destination journal.</p>
<div class="figrow">
<div class="fig"><div class="panel-h">a · Secondary claim follows the primary</div>
<div id="heat"></div>
<div class="cap">When the primary claim was majorly revised, the first secondary claim also changed in <b>90%</b> of pairs, versus only <b>34%</b> when the primary was unchanged.</div></div>
<div class="fig"><div class="panel-h">b · Major-revision rate by primary claim type</div><div class="canvas-box"><canvas id="c_2b"></canvas></div>
<div class="cap"><b>Method</b> claims are the most stable (5.4% major). Secondary claims (red) are revised more often than primary claims (blue) for every type.</div></div>
</div>
<div class="figrow">
<div class="fig"><div class="panel-h">c · Major-revision rate by year of preprint posting</div><div class="canvas-box"><canvas id="c_2c"></canvas></div>
<div class="cap">Major revision fell from <b>17.0% in 2019</b> to <b>5.7% in 2024</b>.</div></div>
<div class="fig"><div class="panel-h">d · Content change by review-time tertile</div><div class="canvas-box"><canvas id="c_2d"></canvas></div>
<div class="cap">Major revision rose from <b>7.0%</b> in the fastest tertile (median 110 days) to <b>14.1%</b> in the slowest (median 416 days).</div></div>
</div>
<div class="figrow">
<div class="fig"><div class="panel-h">e · Any revision vs journal impact (2-yr mean citedness, log scale)</div><div class="canvas-box"><canvas id="c_2e"></canvas></div>
<div class="cap">Revision rises with journal impact and is <b>not linear</b>: a grouped binomial fractional-polynomial model (powers −0.5 and 0) over 59,012 pairs in 736 journals puts the fitted revision probability at <b>53.8%</b> at citedness 2 and <b>67.5%</b> at citedness 10 (OR 1.78, robust 95% CI 1.39–2.29).</div></div>
<div class="fig"><div class="panel-h">f · Retraction rate: bioRxiv-linked vs not linked</div><div class="canvas-box"><canvas id="c_2f"></canvas></div>
<div class="cap">In an article-level cohort of 399,928 papers published 2021–2024 in 47 journals, retraction was <b>less</b> frequent among bioRxiv-linked articles (0.79 vs 5.20 per 10,000 article-years; hazard ratio <b>0.22</b>, 95% CI 0.10–0.50, Cox model stratified by journal and publication year). Exploratory; 6 events in the linked group.</div></div>
</div>
</section>
<!-- VALIDATION -->
<section class="block">
<div class="eyebrow">Validation · Suppl. Figure 2</div>
<h2>The model agrees with the raters as well as the raters agree with each other</h2>
<p class="lead">Four raters independently labelled a stratified subsample of <b>550 pairs</b>, blind to the model. They agreed at a quadratic-weighted Cohen's κ of <b>0.76</b> (Krippendorff's α 0.77). The model reached <b>κ 0.76</b> against the rater consensus and <b>0.67</b> against individual raters, and was within one ordinal level of the consensus on 98.9% of pairs.</p>
<div class="fig" style="margin-top:14px"><div class="canvas-box"><canvas id="c_kappa"></canvas></div></div>
</section>
<div class="footer">
<p>Every number on this page is computed directly from the 72,644-pair dataset and matches <b>Yin, Anh, Forster & Rust, “Tracking claim changes from preprint to publication.”</b></p>
<div class="pill-row">
<span class="pill">72,644 pairs</span><span class="pill">posted 2018–2025</span><span class="pill">3,149 journals</span>
<span class="pill">27 fields</span><span class="pill">Claude Sonnet 4.6</span>
</div>
<p style="margin-top:16px"><a href="browser.html">→ Explore the full dataset</a></p>
</div>
</div><!-- /content -->
</div>
<script>
const C={unchanged:'#1f9d61',minor:'#e0a516',major:'#d6455d',cautious:'#2f6fb0',confident:'#c9711a',
blue:'#1e3a8a',blue2:'#2563eb',coral:'#ff6b6b',grey:'#c2cad6',ink:'#16202e',muted:'#5b6b7e'};
const cap=s=>s?s.charAt(0).toUpperCase()+s.slice(1):'';
const TYPE={mechanism:'Mechanism',association:'Association',descriptive:'Descriptive',method:'Method',therapeutic:'Therapeutic',null_result:'Null result'};
const td=t=>TYPE[t]||cap((t||'').replace(/_/g,' '));
Chart.defaults.font.family="Inter,sans-serif"; Chart.defaults.font.size=12; Chart.defaults.color='#5b6b7e';
const fmtField=f=>cap(f).replace('biology',' biol.').replace('Bioinformatics','Bioinformatics');
fetch('data/stats.json').then(r=>r.json()).then(S=>{
document.getElementById('boot').style.display='none';
document.getElementById('content').style.display='block';
buildKPIs(S); draw(S);
}).catch(e=>{document.getElementById('boot').innerHTML='Could not load data/stats.json — make sure you are viewing this over a local server or GitHub Pages.';});
function buildKPIs(S){
const h=S.headline;
const k=[
[h.n_pairs.toLocaleString(),'preprint–publication pairs'],
[S.fig1a.unchanged+S.fig1a.minor+'%','claims unchanged or minor'],
[S.fig1a.major+'%','primary claims majorly changed'],
[S.fig1b_ratio.toFixed(1)+'×','more cautious than confident']
];
document.getElementById('kpis').innerHTML=k.map(x=>`<div class="kpi"><div class="v">${x[0]}</div><div class="l">${x[1]}</div></div>`).join('');
document.getElementById('k-unch').textContent=S.fig1a.unchanged+'%';
document.getElementById('k-min').textContent=S.fig1a.minor+'%';
document.getElementById('k-maj').textContent=S.fig1a.major+'%';
document.getElementById('k-ratio').textContent=S.fig1b_ratio.toFixed(1)+'×';
}
function pieOpts(title){return{responsive:true,maintainAspectRatio:false,cutout:'58%',
plugins:{legend:{position:'bottom',labels:{boxWidth:12,boxHeight:12,padding:14,font:{size:12.5,weight:'600'}}},
tooltip:{callbacks:{label:c=>` ${c.label}: ${c.parsed}%`}}}};}
function draw(S){
// 1a donut
new Chart(c('c_1a'),{type:'doughnut',data:{labels:['Unchanged','Minor revision','Major change'],
datasets:[{data:[S.fig1a.unchanged,S.fig1a.minor,S.fig1a.major],backgroundColor:[C.unchanged,C.minor,C.major],borderWidth:2,borderColor:'#fff'}]},options:pieOpts()});
// 1b donut
new Chart(c('c_1b'),{type:'doughnut',data:{labels:['Unchanged','More cautious','More confident','Not assessable'],
datasets:[{data:[S.fig1b.unchanged,S.fig1b.weakened,S.fig1b.strengthened,S.fig1b.NA],backgroundColor:[C.grey,C.cautious,C.confident,'#e6eaf0'],borderWidth:2,borderColor:'#fff'}]},options:pieOpts()});
// 1c stacked within stratum
const strata=['unchanged','minor','major'];
new Chart(c('c_1c'),{type:'bar',data:{labels:['Unchanged','Minor','Major'],datasets:[
{label:'More cautious',data:strata.map(s=>S.fig1c[s].cautious),backgroundColor:C.cautious},
{label:'More confident',data:strata.map(s=>S.fig1c[s].confident),backgroundColor:C.confident},
{label:'Hedging unchanged',data:strata.map(s=>S.fig1c[s].unchanged),backgroundColor:C.grey}
]},options:{responsive:true,maintainAspectRatio:false,scales:{x:{stacked:true,title:{display:true,text:'Content change'}},y:{stacked:true,max:100,title:{display:true,text:'% of assessable claims'}}},
plugins:{legend:{position:'bottom',labels:{boxWidth:12,padding:12}},tooltip:{callbacks:{label:cx=>` ${cx.dataset.label}: ${cx.parsed.y}%`}}}}});
// 1d field stacked
const f1d=S.fig1d;
new Chart(c('c_1d'),{type:'bar',data:{labels:f1d.map(x=>fmtField(x.field)),datasets:[
{label:'Unchanged',data:f1d.map(x=>x.unchanged),backgroundColor:C.unchanged},
{label:'Minor',data:f1d.map(x=>x.minor),backgroundColor:C.minor},
{label:'Major',data:f1d.map(x=>x.major),backgroundColor:C.major}
]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,
scales:{x:{stacked:true,max:100,title:{display:true,text:'% of pairs'}},y:{stacked:true,ticks:{font:{size:11}}}},
plugins:{legend:{position:'bottom',labels:{boxWidth:12,padding:12}},tooltip:{callbacks:{label:cx=>` ${cx.dataset.label}: ${cx.parsed.x}%`}}}}});
// 1e ratio by field
const f1e=S.fig1e;
new Chart(c('c_1e'),{type:'bar',data:{labels:f1e.map(x=>fmtField(x.field)),datasets:[
{label:'Strengthened ÷ weakened',data:f1e.map(x=>x.ratio),backgroundColor:f1e.map(x=>x.ratio<1?C.cautious:C.confident)}
]},options:{responsive:true,maintainAspectRatio:false,
scales:{y:{title:{display:true,text:'ratio'},suggestedMax:1},x:{ticks:{font:{size:9.5},maxRotation:70,minRotation:55}}},
plugins:{legend:{display:false},tooltip:{callbacks:{label:cx=>` ratio ${cx.parsed.y}`}},
annotation:false}},plugins:[{afterDraw:ch=>{const y=ch.scales.y.getPixelForValue(1);const a=ch.chartArea,x=ch.ctx;x.save();x.strokeStyle='#d6455d';x.setLineDash([6,4]);x.lineWidth=1.5;x.beginPath();x.moveTo(a.left,y);x.lineTo(a.right,y);x.stroke();x.restore();}}]});
// 2b primary vs secondary by type
const f2b=S.fig2b;
new Chart(c('c_2b'),{type:'bar',data:{labels:f2b.map(x=>td(x.type)),datasets:[
{label:'Primary claim',data:f2b.map(x=>x.primary_major),backgroundColor:C.blue2},
{label:'Secondary claims',data:f2b.map(x=>x.secondary_major),backgroundColor:C.coral}
]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{title:{display:true,text:'% major revision'}}},
plugins:{legend:{position:'bottom',labels:{boxWidth:12,padding:12}},tooltip:{callbacks:{label:cx=>` ${cx.dataset.label}: ${cx.parsed.y}%`}}}}});
// 2c by year line
const f2c=S.fig2c.filter(x=>x.n>=100);
new Chart(c('c_2c'),{type:'line',data:{labels:f2c.map(x=>x.year),datasets:[
{label:'Major',data:f2c.map(x=>x.major),borderColor:C.major,backgroundColor:'rgba(214,69,93,.08)',fill:true,tension:.3,borderWidth:2.5,pointRadius:3},
{label:'Minor',data:f2c.map(x=>x.minor),borderColor:C.minor,tension:.3,borderWidth:2,pointRadius:2},
{label:'Unchanged',data:f2c.map(x=>x.unchanged),borderColor:C.unchanged,tension:.3,borderWidth:2,pointRadius:2}
]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{title:{display:true,text:'% of pairs'}}},
plugins:{legend:{position:'bottom',labels:{boxWidth:12,padding:12}},tooltip:{callbacks:{label:cx=>` ${cx.dataset.label}: ${cx.parsed.y}%`}}}}});
// 2d tertiles stacked
const f2d=S.fig2d;
new Chart(c('c_2d'),{type:'bar',data:{labels:f2d.map(x=>`T${x.tertile} · ${x.median_days}d`),datasets:[
{label:'Unchanged',data:f2d.map(x=>x.unchanged),backgroundColor:C.unchanged},
{label:'Minor',data:f2d.map(x=>x.minor),backgroundColor:C.minor},
{label:'Major',data:f2d.map(x=>x.major),backgroundColor:C.major}
]},options:{responsive:true,maintainAspectRatio:false,scales:{x:{stacked:true,title:{display:true,text:'Review-time tertile (median days)'}},y:{stacked:true,max:100,title:{display:true,text:'% of pairs'}}},
plugins:{legend:{position:'bottom',labels:{boxWidth:12,padding:12}},tooltip:{callbacks:{label:cx=>` ${cx.dataset.label}: ${cx.parsed.y}%`}}}}});
// 2e impact scatter (bubble) + fit
const je=S.fig2e;
new Chart(c('c_2e'),{data:{datasets:[
{type:'line',label:'Fitted FP2 model',data:je.fit,parsing:false,borderColor:C.blue2,borderWidth:2.5,pointRadius:0,tension:.3,order:0},
{type:'bubble',label:'Journal',
data:je.journals.map(o=>({x:o.x,y:o.y,r:Math.max(2,Math.sqrt(o.n)/6),n:o.n})),
backgroundColor:'rgba(37,99,235,.18)',borderColor:'rgba(37,99,235,.45)',borderWidth:.5,order:1}
]},
options:{responsive:true,maintainAspectRatio:false,
scales:{x:{type:'logarithmic',title:{display:true,text:'Journal 2-yr mean citedness (log)'}},y:{title:{display:true,text:'% with any revision'}}},
plugins:{legend:{display:false},tooltip:{callbacks:{label:cx=>cx.dataset.type==='line'
? ` fitted ${cx.parsed.y}%` : ` impact ${cx.raw.x}, revision ${cx.raw.y}%, n=${cx.raw.n}`}}}}});
// 2f retraction
const f=S.fig2f;
new Chart(c('c_2f'),{type:'bar',data:{labels:['bioRxiv-linked','Not linked'],datasets:[
{data:[f.linked_per_10k_article_years,f.unlinked_per_10k_article_years],backgroundColor:[C.blue2,C.major],borderRadius:6,barThickness:74}
]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{title:{display:true,text:'retractions per 10,000 article-years'}}},
plugins:{legend:{display:false},tooltip:{callbacks:{label:cx=>` ${cx.parsed.y} per 10,000 article-years`}}}}});
// kappa
const k=S.kappa;
new Chart(c('c_kappa'),{type:'bar',data:{labels:['Rater vs rater','Model vs rater consensus','Model vs individual rater'],
datasets:[{data:[k.rater_rater,k.model_consensus,k.model_rater],
backgroundColor:[C.muted,C.blue,C.blue2],borderRadius:6,barThickness:60}]},
options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{max:1,title:{display:true,text:"Cohen's κ"}}},
plugins:{legend:{display:false},tooltip:{callbacks:{label:cx=>` κ = ${cx.parsed.x}`}}}}});
drawHeat(S.fig2a); drawAlluvial(S.fig1f,S.fig1f_total);
}
function c(id){return document.getElementById(id).getContext('2d');}
function drawHeat(h){
const rows=['unchanged','minor','major'], cols=['unchanged','minor','major'];
const colColor={unchanged:C.unchanged,minor:C.minor,major:C.major};
let html='<div class="heat"><div class="hhdr"></div>'+cols.map(cc=>`<div class="hhdr">S1 ${cc}</div>`).join('');
rows.forEach(r=>{
html+=`<div class="hrow">Primary ${cap(r)}</div>`;
cols.forEach(cc=>{
const v=h[r][cc]; const a=0.12+0.85*(v/100);
const dark=v>55;
html+=`<div class="hcell" style="background:rgba(37,99,235,${a});color:${dark?'#fff':'#16202e'}">${v}%</div>`;
});
});
html+='</div>';
document.getElementById('heat').innerHTML=html;
}
function drawAlluvial(trans,total){
// aggregate flows between canonical types, draw left->right ribbons
const order=['mechanism','association','descriptive','method','therapeutic','null_result'];
const colors={mechanism:'#2563eb',association:'#7c4dff',descriptive:'#1f9d61',method:'#d99100',therapeutic:'#d6455d',null_result:'#5b6b7e'};
const left={},right={};
order.forEach(t=>{left[t]=0;right[t]=0;});
trans.forEach(f=>{left[f.from]+=f.n;right[f.to]+=f.n;});
const svg=document.getElementById('alluvial');
const W=720,H=420,padT=20,padB=20,colW=130,gap=6;
const leftTypes=order.filter(t=>left[t]>0), rightTypes=order.filter(t=>right[t]>0);
const totL=leftTypes.reduce((s,t)=>s+left[t],0), totR=rightTypes.reduce((s,t)=>s+right[t],0);
const avail=H-padT-padB;
function layout(types,vals,tot){
const n=types.length; const usable=avail-gap*(n-1); let y=padT; const pos={};
types.forEach(t=>{const hgt=Math.max(8,usable*vals[t]/tot);pos[t]={y0:y,y1:y+hgt};y+=hgt+gap;});
return pos;
}
const Lpos=layout(leftTypes,left,totL), Rpos=layout(rightTypes,right,totR);
const xL=colW, xR=W-colW;
let s='';
// ribbons (sort big first)
const cursorL={},cursorR={};
leftTypes.forEach(t=>cursorL[t]=Lpos[t].y0); rightTypes.forEach(t=>cursorR[t]=Rpos[t].y0);
const sorted=[...trans].sort((a,b)=>b.n-a.n);
const scaleL=avail/ (totL)*(avail/avail);
sorted.forEach(f=>{
const hL=Math.max(1,(Lpos[f.from].y1-Lpos[f.from].y0)*f.n/left[f.from]);
const hR=Math.max(1,(Rpos[f.to].y1-Rpos[f.to].y0)*f.n/right[f.to]);
const y0=cursorL[f.from], y1=cursorR[f.to];
cursorL[f.from]+=hL; cursorR[f.to]+=hR;
const c1=xL+ (xR-xL)*0.5;
s+=`<path d="M${xL},${y0} C${c1},${y0} ${c1},${y1} ${xR},${y1} L${xR},${y1+hR} C${c1},${y1+hR} ${c1},${y0+hL} ${xL},${y0+hL} Z"
fill="${colors[f.from]}" opacity="0.32"><title>${td(f.from)} → ${td(f.to)}: ${f.n} pairs</title></path>`;
});
// nodes
function nodes(types,pos,x,side){
types.forEach(t=>{
const y0=pos[t].y0,y1=pos[t].y1;
s+=`<rect x="${x-9}" y="${y0}" width="9" height="${y1-y0}" rx="2" fill="${colors[t]}"/>`;
const ty=(y0+y1)/2;
if(side==='L') s+=`<text x="${x-15}" y="${ty+4}" text-anchor="end" font-size="12" font-weight="600" fill="#16202e">${td(t)}</text>`;
else s+=`<text x="${x+15}" y="${ty+4}" text-anchor="start" font-size="12" font-weight="600" fill="#16202e">${td(t)}</text>`;
});
}
nodes(leftTypes,Lpos,xL,'L'); nodes(rightTypes,Rpos,xR,'R');
s+=`<text x="${xL}" y="13" text-anchor="middle" font-size="11" font-weight="800" fill="#5b6b7e">PREPRINT</text>`;
s+=`<text x="${xR}" y="13" text-anchor="middle" font-size="11" font-weight="800" fill="#5b6b7e">PUBLISHED</text>`;
svg.innerHTML=s;
}
</script>
</body>
</html>