Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Commit ·
7db0003
1
Parent(s): 23fd567
improved plots for mobile
Browse files
app/src/content/embeds/d3-benchmark-comparison.html
CHANGED
|
@@ -45,6 +45,7 @@
|
|
| 45 |
.d3-benchmark-comparison { position: relative; }
|
| 46 |
.d3-benchmark-comparison .controls {
|
| 47 |
display: flex;
|
|
|
|
| 48 |
gap: 16px;
|
| 49 |
align-items: flex-end;
|
| 50 |
justify-content: center;
|
|
@@ -158,6 +159,28 @@
|
|
| 158 |
margin-right: 6px;
|
| 159 |
vertical-align: middle;
|
| 160 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
</style>
|
| 162 |
<script>
|
| 163 |
(() => {
|
|
@@ -376,7 +399,8 @@
|
|
| 376 |
tipInner.innerHTML = html;
|
| 377 |
const tipW = tip.offsetWidth || 180;
|
| 378 |
const cW = container.clientWidth || 800;
|
| 379 |
-
const
|
|
|
|
| 380 |
tip.style.transform = `translate(${px}px, ${Math.max(0, y - 20)}px)`;
|
| 381 |
tip.style.opacity = '1';
|
| 382 |
}
|
|
@@ -411,8 +435,8 @@
|
|
| 411 |
// ─── BAR CHART ───
|
| 412 |
function renderBar() {
|
| 413 |
const width = container.clientWidth || 800;
|
|
|
|
| 414 |
const hasBaselines = allData.some(r => isBaseline(r[RUN_COL]));
|
| 415 |
-
const margin = { top: hasBaselines ? 20 : 12, right: 56, bottom: 32, left: 190 };
|
| 416 |
|
| 417 |
const grouped = d3.group(allData, d => d[RUN_COL]);
|
| 418 |
const finalData = [];
|
|
@@ -425,6 +449,17 @@
|
|
| 425 |
|
| 426 |
const barData = finalData.filter(d => !isBaseline(d.rawName));
|
| 427 |
const baselineData = finalData.filter(d => isBaseline(d.rawName));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
|
| 429 |
const barHeight = 28, barGap = 8;
|
| 430 |
const height = margin.top + margin.bottom + barData.length * (barHeight + barGap);
|
|
@@ -446,9 +481,9 @@
|
|
| 446 |
// X axis
|
| 447 |
gRoot.selectAll('.axis-x').data([0]).join('g').attr('class', 'axes axis-x')
|
| 448 |
.attr('transform', `translate(0,${innerHeight})`)
|
| 449 |
-
.call(d3.axisBottom(x).ticks(5).tickFormat(d3.format('.2f')).tickSizeOuter(0))
|
| 450 |
.call(g => {
|
| 451 |
-
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', '11px');
|
| 452 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 453 |
});
|
| 454 |
|
|
@@ -456,7 +491,7 @@
|
|
| 456 |
gRoot.selectAll('.axis-y').data([0]).join('g').attr('class', 'axes axis-y')
|
| 457 |
.call(d3.axisLeft(y).tickSizeOuter(0))
|
| 458 |
.call(g => {
|
| 459 |
-
g.selectAll('text').attr('fill', 'var(--text-color)').style('font-size', '12px').style('font-weight', '500');
|
| 460 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 461 |
});
|
| 462 |
|
|
@@ -504,7 +539,7 @@
|
|
| 504 |
gRoot.selectAll('text.value-label').data(barData, d => d.name).join(
|
| 505 |
enter => enter.append('text').attr('class', 'value-label')
|
| 506 |
.attr('x', d => x(d.value) + 5).attr('y', d => y(d.name) + y.bandwidth() / 2)
|
| 507 |
-
.attr('dy', '0.35em').attr('fill', 'var(--text-color)').attr('font-size', 11)
|
| 508 |
.text(d => d.value.toFixed(3)),
|
| 509 |
update => update.transition().duration(300)
|
| 510 |
.attr('x', d => x(d.value) + 5).attr('y', d => y(d.name) + y.bandwidth() / 2)
|
|
@@ -529,7 +564,7 @@
|
|
| 529 |
enter => enter.append('text').attr('class', 'baseline-vlabel baseline')
|
| 530 |
.attr('x', d => x(d.value)).attr('y', -4)
|
| 531 |
.attr('text-anchor', 'middle').attr('fill', d => colorMap[d.rawName] || '#999')
|
| 532 |
-
.attr('font-size', 11).attr('font-weight', 600)
|
| 533 |
.text(d => `${d.name} (${d.value.toFixed(3)})`),
|
| 534 |
update => update.transition().duration(300)
|
| 535 |
.attr('x', d => x(d.value))
|
|
@@ -541,9 +576,10 @@
|
|
| 541 |
// ─── LINE CHART ───
|
| 542 |
function renderLine() {
|
| 543 |
const width = container.clientWidth || 800;
|
|
|
|
| 544 |
const hasBaselines = allData.some(r => isBaseline(r[RUN_COL]));
|
| 545 |
-
const margin = { top: 16, right: 50, bottom: 48, left: 60 };
|
| 546 |
-
const height = Math.max(300, Math.round(width / 2.5));
|
| 547 |
svg.attr('width', width).attr('height', height);
|
| 548 |
gRoot.attr('transform', `translate(${margin.left},${margin.top})`);
|
| 549 |
|
|
@@ -581,29 +617,34 @@
|
|
| 581 |
// X axis
|
| 582 |
gRoot.selectAll('.axis-x').data([0]).join('g').attr('class', 'axes axis-x')
|
| 583 |
.attr('transform', `translate(0,${innerHeight})`)
|
| 584 |
-
.call(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
.call(g => {
|
| 586 |
-
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', '10px');
|
| 587 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 588 |
});
|
| 589 |
|
| 590 |
// Y axis
|
| 591 |
gRoot.selectAll('.axis-y').data([0]).join('g').attr('class', 'axes axis-y')
|
| 592 |
-
.call(d3.axisLeft(y).ticks(6).tickFormat(d3.format('.2f')).tickSizeOuter(0))
|
| 593 |
.call(g => {
|
| 594 |
-
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', '11px');
|
| 595 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 596 |
});
|
| 597 |
|
| 598 |
// Axis labels
|
| 599 |
gRoot.selectAll('.x-label').data([0]).join('text').attr('class', 'x-label')
|
| 600 |
-
.attr('x', innerWidth / 2).attr('y', innerHeight + 38)
|
| 601 |
-
.attr('text-anchor', 'middle').attr('fill', 'var(--text-color)').attr('font-size', 12)
|
| 602 |
.text('Tokens (Steps)');
|
| 603 |
|
| 604 |
gRoot.selectAll('.y-label').data([0]).join('text').attr('class', 'y-label')
|
| 605 |
-
.attr('transform', 'rotate(-90)').attr('x', -innerHeight / 2).attr('y', -44)
|
| 606 |
-
.attr('text-anchor', 'middle').attr('fill', 'var(--text-color)').attr('font-size', 12)
|
| 607 |
.text(metricName(currentMetric));
|
| 608 |
|
| 609 |
// Baseline horizontal reference lines
|
|
@@ -624,7 +665,7 @@
|
|
| 624 |
.attr('x', 4).attr('y', d => y(d.finalValue) - 6)
|
| 625 |
.attr('text-anchor', 'start')
|
| 626 |
.attr('fill', d => colorMap[d.rawName] || '#999')
|
| 627 |
-
.attr('font-size', 10).attr('font-weight', 600)
|
| 628 |
.text(d => `${d.name} (${d.finalValue.toFixed(3)})`),
|
| 629 |
update => update.transition().duration(300)
|
| 630 |
.attr('x', 4).attr('y', d => y(d.finalValue) - 6)
|
|
|
|
| 45 |
.d3-benchmark-comparison { position: relative; }
|
| 46 |
.d3-benchmark-comparison .controls {
|
| 47 |
display: flex;
|
| 48 |
+
flex-wrap: wrap;
|
| 49 |
gap: 16px;
|
| 50 |
align-items: flex-end;
|
| 51 |
justify-content: center;
|
|
|
|
| 159 |
margin-right: 6px;
|
| 160 |
vertical-align: middle;
|
| 161 |
}
|
| 162 |
+
@media (max-width: 640px) {
|
| 163 |
+
.d3-benchmark-comparison .controls {
|
| 164 |
+
flex-direction: column;
|
| 165 |
+
align-items: stretch;
|
| 166 |
+
gap: 10px;
|
| 167 |
+
}
|
| 168 |
+
.d3-benchmark-comparison .controls .control-group {
|
| 169 |
+
width: 100%;
|
| 170 |
+
}
|
| 171 |
+
.d3-benchmark-comparison .controls select {
|
| 172 |
+
width: 100%;
|
| 173 |
+
}
|
| 174 |
+
.d3-benchmark-comparison .legend .item {
|
| 175 |
+
white-space: normal;
|
| 176 |
+
align-items: flex-start;
|
| 177 |
+
line-height: 1.2;
|
| 178 |
+
}
|
| 179 |
+
.d3-benchmark-comparison .legend .swatch {
|
| 180 |
+
flex-shrink: 0;
|
| 181 |
+
margin-top: 1px;
|
| 182 |
+
}
|
| 183 |
+
}
|
| 184 |
</style>
|
| 185 |
<script>
|
| 186 |
(() => {
|
|
|
|
| 399 |
tipInner.innerHTML = html;
|
| 400 |
const tipW = tip.offsetWidth || 180;
|
| 401 |
const cW = container.clientWidth || 800;
|
| 402 |
+
const preferredX = (x + tipW + 20 > cW) ? x - tipW - 12 : x + 12;
|
| 403 |
+
const px = Math.max(0, Math.min(preferredX, Math.max(0, cW - tipW - 6)));
|
| 404 |
tip.style.transform = `translate(${px}px, ${Math.max(0, y - 20)}px)`;
|
| 405 |
tip.style.opacity = '1';
|
| 406 |
}
|
|
|
|
| 435 |
// ─── BAR CHART ───
|
| 436 |
function renderBar() {
|
| 437 |
const width = container.clientWidth || 800;
|
| 438 |
+
const isMobile = width < 640;
|
| 439 |
const hasBaselines = allData.some(r => isBaseline(r[RUN_COL]));
|
|
|
|
| 440 |
|
| 441 |
const grouped = d3.group(allData, d => d[RUN_COL]);
|
| 442 |
const finalData = [];
|
|
|
|
| 449 |
|
| 450 |
const barData = finalData.filter(d => !isBaseline(d.rawName));
|
| 451 |
const baselineData = finalData.filter(d => isBaseline(d.rawName));
|
| 452 |
+
const maxLabelChars = d3.max(finalData, d => d.name.length) || 0;
|
| 453 |
+
const desiredLeft = Math.max(
|
| 454 |
+
isMobile ? 92 : 150,
|
| 455 |
+
Math.round(maxLabelChars * (isMobile ? 5.2 : 6.3))
|
| 456 |
+
);
|
| 457 |
+
const margin = {
|
| 458 |
+
top: hasBaselines ? 20 : 12,
|
| 459 |
+
right: isMobile ? 40 : 56,
|
| 460 |
+
bottom: isMobile ? 30 : 32,
|
| 461 |
+
left: Math.min(desiredLeft, isMobile ? 126 : 220),
|
| 462 |
+
};
|
| 463 |
|
| 464 |
const barHeight = 28, barGap = 8;
|
| 465 |
const height = margin.top + margin.bottom + barData.length * (barHeight + barGap);
|
|
|
|
| 481 |
// X axis
|
| 482 |
gRoot.selectAll('.axis-x').data([0]).join('g').attr('class', 'axes axis-x')
|
| 483 |
.attr('transform', `translate(0,${innerHeight})`)
|
| 484 |
+
.call(d3.axisBottom(x).ticks(isMobile ? 4 : 5).tickFormat(d3.format('.2f')).tickSizeOuter(0))
|
| 485 |
.call(g => {
|
| 486 |
+
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', isMobile ? '10px' : '11px');
|
| 487 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 488 |
});
|
| 489 |
|
|
|
|
| 491 |
gRoot.selectAll('.axis-y').data([0]).join('g').attr('class', 'axes axis-y')
|
| 492 |
.call(d3.axisLeft(y).tickSizeOuter(0))
|
| 493 |
.call(g => {
|
| 494 |
+
g.selectAll('text').attr('fill', 'var(--text-color)').style('font-size', isMobile ? '11px' : '12px').style('font-weight', '500');
|
| 495 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 496 |
});
|
| 497 |
|
|
|
|
| 539 |
gRoot.selectAll('text.value-label').data(barData, d => d.name).join(
|
| 540 |
enter => enter.append('text').attr('class', 'value-label')
|
| 541 |
.attr('x', d => x(d.value) + 5).attr('y', d => y(d.name) + y.bandwidth() / 2)
|
| 542 |
+
.attr('dy', '0.35em').attr('fill', 'var(--text-color)').attr('font-size', isMobile ? 10 : 11)
|
| 543 |
.text(d => d.value.toFixed(3)),
|
| 544 |
update => update.transition().duration(300)
|
| 545 |
.attr('x', d => x(d.value) + 5).attr('y', d => y(d.name) + y.bandwidth() / 2)
|
|
|
|
| 564 |
enter => enter.append('text').attr('class', 'baseline-vlabel baseline')
|
| 565 |
.attr('x', d => x(d.value)).attr('y', -4)
|
| 566 |
.attr('text-anchor', 'middle').attr('fill', d => colorMap[d.rawName] || '#999')
|
| 567 |
+
.attr('font-size', isMobile ? 10 : 11).attr('font-weight', 600)
|
| 568 |
.text(d => `${d.name} (${d.value.toFixed(3)})`),
|
| 569 |
update => update.transition().duration(300)
|
| 570 |
.attr('x', d => x(d.value))
|
|
|
|
| 576 |
// ─── LINE CHART ───
|
| 577 |
function renderLine() {
|
| 578 |
const width = container.clientWidth || 800;
|
| 579 |
+
const isMobile = width < 640;
|
| 580 |
const hasBaselines = allData.some(r => isBaseline(r[RUN_COL]));
|
| 581 |
+
const margin = { top: 16, right: isMobile ? 18 : 50, bottom: isMobile ? 42 : 48, left: isMobile ? 46 : 60 };
|
| 582 |
+
const height = Math.max(isMobile ? 260 : 300, Math.round(width / (isMobile ? 1.95 : 2.5)));
|
| 583 |
svg.attr('width', width).attr('height', height);
|
| 584 |
gRoot.attr('transform', `translate(${margin.left},${margin.top})`);
|
| 585 |
|
|
|
|
| 617 |
// X axis
|
| 618 |
gRoot.selectAll('.axis-x').data([0]).join('g').attr('class', 'axes axis-x')
|
| 619 |
.attr('transform', `translate(0,${innerHeight})`)
|
| 620 |
+
.call(
|
| 621 |
+
d3.axisBottom(x)
|
| 622 |
+
.ticks(isMobile ? 4 : 6)
|
| 623 |
+
.tickFormat(d => isMobile ? formatTokens(stepsToTokens(d)) : stepLabelShort(d))
|
| 624 |
+
.tickSizeOuter(0)
|
| 625 |
+
)
|
| 626 |
.call(g => {
|
| 627 |
+
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', isMobile ? '9px' : '10px');
|
| 628 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 629 |
});
|
| 630 |
|
| 631 |
// Y axis
|
| 632 |
gRoot.selectAll('.axis-y').data([0]).join('g').attr('class', 'axes axis-y')
|
| 633 |
+
.call(d3.axisLeft(y).ticks(isMobile ? 5 : 6).tickFormat(d3.format('.2f')).tickSizeOuter(0))
|
| 634 |
.call(g => {
|
| 635 |
+
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', isMobile ? '10px' : '11px');
|
| 636 |
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 637 |
});
|
| 638 |
|
| 639 |
// Axis labels
|
| 640 |
gRoot.selectAll('.x-label').data([0]).join('text').attr('class', 'x-label')
|
| 641 |
+
.attr('x', innerWidth / 2).attr('y', innerHeight + (isMobile ? 32 : 38))
|
| 642 |
+
.attr('text-anchor', 'middle').attr('fill', 'var(--text-color)').attr('font-size', isMobile ? 11 : 12)
|
| 643 |
.text('Tokens (Steps)');
|
| 644 |
|
| 645 |
gRoot.selectAll('.y-label').data([0]).join('text').attr('class', 'y-label')
|
| 646 |
+
.attr('transform', 'rotate(-90)').attr('x', -innerHeight / 2).attr('y', isMobile ? -34 : -44)
|
| 647 |
+
.attr('text-anchor', 'middle').attr('fill', 'var(--text-color)').attr('font-size', isMobile ? 11 : 12)
|
| 648 |
.text(metricName(currentMetric));
|
| 649 |
|
| 650 |
// Baseline horizontal reference lines
|
|
|
|
| 665 |
.attr('x', 4).attr('y', d => y(d.finalValue) - 6)
|
| 666 |
.attr('text-anchor', 'start')
|
| 667 |
.attr('fill', d => colorMap[d.rawName] || '#999')
|
| 668 |
+
.attr('font-size', isMobile ? 9 : 10).attr('font-weight', 600)
|
| 669 |
.text(d => `${d.name} (${d.finalValue.toFixed(3)})`),
|
| 670 |
update => update.transition().duration(300)
|
| 671 |
.attr('x', 4).attr('y', d => y(d.finalValue) - 6)
|
app/src/content/embeds/score-correlation.html
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
<div class="d3-score-correlation" style="width:100%;margin:10px 0;min-height:400px;"></div>
|
| 2 |
<style>
|
| 3 |
-
.d3-score-correlation { font-family: system-ui, -apple-system, sans-serif; }
|
| 4 |
.d3-score-correlation .d3-tooltip {
|
| 5 |
position: absolute; top: 0; left: 0;
|
| 6 |
transform: translate(-9999px, -9999px);
|
|
@@ -29,6 +29,10 @@
|
|
| 29 |
.d3-score-correlation .legend .swatch {
|
| 30 |
width: 20px; height: 14px; border-radius: 3px; border: 1px solid var(--border-color);
|
| 31 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
</style>
|
| 33 |
<script>
|
| 34 |
(() => {
|
|
@@ -291,6 +295,7 @@
|
|
| 291 |
|
| 292 |
const render = () => {
|
| 293 |
const width = container.clientWidth || 900;
|
|
|
|
| 294 |
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
| 295 |
const divColor = isDark ? 'rgba(255,255,255,0.22)' : 'rgba(0,0,0,0.18)';
|
| 296 |
const textCol = isDark ? 'rgba(255,255,255,0.8)' : 'rgba(0,0,0,0.7)';
|
|
@@ -299,14 +304,14 @@
|
|
| 299 |
const predLabels = PREDICTORS.map(p => p.label);
|
| 300 |
|
| 301 |
// Layout
|
| 302 |
-
const leftMargin = 140;
|
| 303 |
-
const topMargin = 130; // extra room for two-tier header
|
| 304 |
-
const rightMargin = 10;
|
| 305 |
const bottomMargin = 10;
|
| 306 |
-
const
|
| 307 |
-
const
|
| 308 |
-
const
|
| 309 |
-
const rowGap = 8; // gap between DCLM and EDU groups
|
| 310 |
const plotH = cellH * predLabels.length + rowGap;
|
| 311 |
const totalW = leftMargin + plotW + rightMargin;
|
| 312 |
const totalH = topMargin + plotH + bottomMargin;
|
|
@@ -333,7 +338,6 @@
|
|
| 333 |
// --- Group dividers (vertical) and header labels ---
|
| 334 |
let colOffset = 0;
|
| 335 |
const groupHeaderY = 18; // top-level group name
|
| 336 |
-
const colLabelY = topMargin - 6; // individual column labels
|
| 337 |
|
| 338 |
GROUPS.forEach((grp, gi) => {
|
| 339 |
const groupStartX = colOffset * cellW;
|
|
@@ -349,25 +353,27 @@
|
|
| 349 |
.attr('stroke-dasharray', gi === 1 ? 'none' : '4,3');
|
| 350 |
}
|
| 351 |
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
.
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
.
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
|
|
|
|
|
|
| 371 |
|
| 372 |
colOffset += grp.targets.length;
|
| 373 |
});
|
|
@@ -409,16 +415,16 @@
|
|
| 409 |
.attr('y', (cellH - 1) / 2)
|
| 410 |
.attr('text-anchor', 'middle')
|
| 411 |
.attr('dominant-baseline', 'central')
|
| 412 |
-
.attr('font-size', Math.max(9, Math.min(12, cellW * 0.
|
| 413 |
.attr('font-weight', d => Math.abs(d.r) > 0.4 ? '700' : '500')
|
| 414 |
.attr('fill', d => textFill(d.r))
|
| 415 |
.text(d => d.r.toFixed(2));
|
| 416 |
|
| 417 |
// Significance markers
|
| 418 |
cells.append('text')
|
| 419 |
-
.attr('x', cellW -
|
| 420 |
.attr('text-anchor', 'end')
|
| 421 |
-
.attr('font-size', '11px')
|
| 422 |
.attr('font-weight', '700')
|
| 423 |
.attr('fill', d => Math.abs(d.r) > 0.45 ? 'rgba(255,255,255,0.8)' : mutedCol)
|
| 424 |
.text(d => d.p < 0.001 ? '***' : d.p < 0.01 ? '**' : d.p < 0.05 ? '*' : '');
|
|
@@ -428,15 +434,21 @@
|
|
| 428 |
PREDICTORS.forEach((pred, i) => {
|
| 429 |
const labelG = gLabels.append('g')
|
| 430 |
.style('cursor', 'help');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
|
| 432 |
labelG.append('text')
|
| 433 |
.attr('x', 0).attr('y', rowY(i) + cellH / 2)
|
| 434 |
.attr('text-anchor', 'end')
|
| 435 |
.attr('dominant-baseline', 'central')
|
| 436 |
-
.attr('font-size', '11px')
|
| 437 |
.attr('fill', textCol)
|
| 438 |
.attr('font-weight', '500')
|
| 439 |
-
.text(
|
| 440 |
|
| 441 |
// Hit area
|
| 442 |
labelG.append('rect')
|
|
@@ -470,9 +482,9 @@
|
|
| 470 |
|
| 471 |
labelG.append('text')
|
| 472 |
.attr('x', 0).attr('y', 0)
|
| 473 |
-
.attr('transform',
|
| 474 |
.attr('text-anchor', 'start')
|
| 475 |
-
.attr('font-size', '10px')
|
| 476 |
.attr('fill', textCol)
|
| 477 |
.attr('font-weight', tgt.isAgg ? '700' : '400')
|
| 478 |
.text(tgt.label);
|
|
@@ -501,51 +513,52 @@
|
|
| 501 |
}
|
| 502 |
});
|
| 503 |
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
.
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
.
|
| 532 |
-
|
| 533 |
-
|
|
|
|
| 534 |
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
});
|
| 548 |
-
}
|
| 549 |
|
| 550 |
// --- Tooltip interactions ---
|
| 551 |
cells.on('mouseenter', function(ev, d) {
|
|
@@ -603,7 +616,7 @@
|
|
| 603 |
<span class="item"><span class="swatch" style="background:${sw(0)};"></span><span>ρ = 0</span></span>
|
| 604 |
<span class="item"><span class="swatch" style="background:${sw(0.3)};"></span><span>ρ = +0.3</span></span>
|
| 605 |
<span class="item"><span class="swatch" style="background:${sw(0.6)};"></span><span>ρ = +0.6</span></span>
|
| 606 |
-
<span style="margin-
|
| 607 |
</div>`;
|
| 608 |
container.appendChild(legend);
|
| 609 |
}
|
|
|
|
| 1 |
<div class="d3-score-correlation" style="width:100%;margin:10px 0;min-height:400px;"></div>
|
| 2 |
<style>
|
| 3 |
+
.d3-score-correlation { font-family: system-ui, -apple-system, sans-serif; position: relative; overflow-x: hidden; }
|
| 4 |
.d3-score-correlation .d3-tooltip {
|
| 5 |
position: absolute; top: 0; left: 0;
|
| 6 |
transform: translate(-9999px, -9999px);
|
|
|
|
| 29 |
.d3-score-correlation .legend .swatch {
|
| 30 |
width: 20px; height: 14px; border-radius: 3px; border: 1px solid var(--border-color);
|
| 31 |
}
|
| 32 |
+
@media (max-width: 640px) {
|
| 33 |
+
.d3-score-correlation .legend .item { font-size: 10px; }
|
| 34 |
+
.d3-score-correlation .legend .swatch { width: 16px; height: 12px; }
|
| 35 |
+
}
|
| 36 |
</style>
|
| 37 |
<script>
|
| 38 |
(() => {
|
|
|
|
| 295 |
|
| 296 |
const render = () => {
|
| 297 |
const width = container.clientWidth || 900;
|
| 298 |
+
const isMobile = width < 640;
|
| 299 |
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
| 300 |
const divColor = isDark ? 'rgba(255,255,255,0.22)' : 'rgba(0,0,0,0.18)';
|
| 301 |
const textCol = isDark ? 'rgba(255,255,255,0.8)' : 'rgba(0,0,0,0.7)';
|
|
|
|
| 304 |
const predLabels = PREDICTORS.map(p => p.label);
|
| 305 |
|
| 306 |
// Layout
|
| 307 |
+
const leftMargin = isMobile ? 126 : 140;
|
| 308 |
+
const topMargin = isMobile ? 90 : 130; // extra room for two-tier header on desktop
|
| 309 |
+
const rightMargin = isMobile ? 8 : 10;
|
| 310 |
const bottomMargin = 10;
|
| 311 |
+
const plotW = Math.max(220, width - leftMargin - rightMargin);
|
| 312 |
+
const cellW = plotW / ALL_TARGETS.length;
|
| 313 |
+
const cellH = isMobile ? 26 : Math.max(28, Math.min(42, cellW * 0.82));
|
| 314 |
+
const rowGap = isMobile ? 6 : 8; // gap between DCLM and EDU groups
|
| 315 |
const plotH = cellH * predLabels.length + rowGap;
|
| 316 |
const totalW = leftMargin + plotW + rightMargin;
|
| 317 |
const totalH = topMargin + plotH + bottomMargin;
|
|
|
|
| 338 |
// --- Group dividers (vertical) and header labels ---
|
| 339 |
let colOffset = 0;
|
| 340 |
const groupHeaderY = 18; // top-level group name
|
|
|
|
| 341 |
|
| 342 |
GROUPS.forEach((grp, gi) => {
|
| 343 |
const groupStartX = colOffset * cellW;
|
|
|
|
| 353 |
.attr('stroke-dasharray', gi === 1 ? 'none' : '4,3');
|
| 354 |
}
|
| 355 |
|
| 356 |
+
if (!isMobile) {
|
| 357 |
+
// Group header label (top tier)
|
| 358 |
+
svg.append('text')
|
| 359 |
+
.attr('x', leftMargin + groupStartX + groupW / 2)
|
| 360 |
+
.attr('y', groupHeaderY)
|
| 361 |
+
.attr('text-anchor', 'middle')
|
| 362 |
+
.attr('font-size', '9.5px')
|
| 363 |
+
.attr('font-weight', '700')
|
| 364 |
+
.attr('letter-spacing', '0.5px')
|
| 365 |
+
.attr('fill', mutedCol)
|
| 366 |
+
.text(grp.name.toUpperCase());
|
| 367 |
+
|
| 368 |
+
// Bracket line under group header
|
| 369 |
+
const bracketY = groupHeaderY + 8;
|
| 370 |
+
svg.append('line')
|
| 371 |
+
.attr('x1', leftMargin + groupStartX + 4)
|
| 372 |
+
.attr('x2', leftMargin + groupStartX + groupW - 4)
|
| 373 |
+
.attr('y1', bracketY).attr('y2', bracketY)
|
| 374 |
+
.attr('stroke', mutedCol)
|
| 375 |
+
.attr('stroke-width', 0.8);
|
| 376 |
+
}
|
| 377 |
|
| 378 |
colOffset += grp.targets.length;
|
| 379 |
});
|
|
|
|
| 415 |
.attr('y', (cellH - 1) / 2)
|
| 416 |
.attr('text-anchor', 'middle')
|
| 417 |
.attr('dominant-baseline', 'central')
|
| 418 |
+
.attr('font-size', Math.max(isMobile ? 7.5 : 9, Math.min(isMobile ? 10 : 12, cellW * 0.25)) + 'px')
|
| 419 |
.attr('font-weight', d => Math.abs(d.r) > 0.4 ? '700' : '500')
|
| 420 |
.attr('fill', d => textFill(d.r))
|
| 421 |
.text(d => d.r.toFixed(2));
|
| 422 |
|
| 423 |
// Significance markers
|
| 424 |
cells.append('text')
|
| 425 |
+
.attr('x', cellW - 2).attr('y', isMobile ? 8 : 10)
|
| 426 |
.attr('text-anchor', 'end')
|
| 427 |
+
.attr('font-size', isMobile ? '8px' : '11px')
|
| 428 |
.attr('font-weight', '700')
|
| 429 |
.attr('fill', d => Math.abs(d.r) > 0.45 ? 'rgba(255,255,255,0.8)' : mutedCol)
|
| 430 |
.text(d => d.p < 0.001 ? '***' : d.p < 0.01 ? '**' : d.p < 0.05 ? '*' : '');
|
|
|
|
| 434 |
PREDICTORS.forEach((pred, i) => {
|
| 435 |
const labelG = gLabels.append('g')
|
| 436 |
.style('cursor', 'help');
|
| 437 |
+
const labelText = isMobile
|
| 438 |
+
? pred.label
|
| 439 |
+
.replace('Input ', 'In ')
|
| 440 |
+
.replace('Output ', 'Out ')
|
| 441 |
+
.replace('Improvement %', 'Δ%')
|
| 442 |
+
: pred.label;
|
| 443 |
|
| 444 |
labelG.append('text')
|
| 445 |
.attr('x', 0).attr('y', rowY(i) + cellH / 2)
|
| 446 |
.attr('text-anchor', 'end')
|
| 447 |
.attr('dominant-baseline', 'central')
|
| 448 |
+
.attr('font-size', isMobile ? '10px' : '11px')
|
| 449 |
.attr('fill', textCol)
|
| 450 |
.attr('font-weight', '500')
|
| 451 |
+
.text(labelText);
|
| 452 |
|
| 453 |
// Hit area
|
| 454 |
labelG.append('rect')
|
|
|
|
| 482 |
|
| 483 |
labelG.append('text')
|
| 484 |
.attr('x', 0).attr('y', 0)
|
| 485 |
+
.attr('transform', `rotate(${isMobile ? -62 : -55})`)
|
| 486 |
.attr('text-anchor', 'start')
|
| 487 |
+
.attr('font-size', isMobile ? '8px' : '10px')
|
| 488 |
.attr('fill', textCol)
|
| 489 |
.attr('font-weight', tgt.isAgg ? '700' : '400')
|
| 490 |
.text(tgt.label);
|
|
|
|
| 513 |
}
|
| 514 |
});
|
| 515 |
|
| 516 |
+
if (!isMobile) {
|
| 517 |
+
// --- Predictor group labels (vertical) ---
|
| 518 |
+
const dclmCenterY = topMargin + (rowY(0) + rowY(DCLM_COUNT - 1) + cellH) / 2;
|
| 519 |
+
const eduCenterY = topMargin + (rowY(DCLM_COUNT) + rowY(PREDICTORS.length - 1) + cellH) / 2;
|
| 520 |
+
const groupLabelX = 14;
|
| 521 |
+
|
| 522 |
+
const GROUP_DESC = {
|
| 523 |
+
'DCLM': 'DCLM score rates text quality on a 0–1 scale using a fastText classifier trained to distinguish curated, high-quality web data from random web crawls.',
|
| 524 |
+
'EDU': 'FineWeb-Edu score rates educational value on a 0–5 scale using a classifier trained on LLM-annotated web pages, where higher scores indicate more instructive content.',
|
| 525 |
+
};
|
| 526 |
+
|
| 527 |
+
[['DCLM', dclmCenterY], ['EDU', eduCenterY]].forEach(([text, cy]) => {
|
| 528 |
+
const labelG = svg.append('g').style('cursor', 'help');
|
| 529 |
+
|
| 530 |
+
labelG.append('text')
|
| 531 |
+
.attr('x', groupLabelX).attr('y', cy)
|
| 532 |
+
.attr('text-anchor', 'middle')
|
| 533 |
+
.attr('dominant-baseline', 'central')
|
| 534 |
+
.attr('font-size', '9px')
|
| 535 |
+
.attr('font-weight', '700')
|
| 536 |
+
.attr('letter-spacing', '1px')
|
| 537 |
+
.attr('fill', isDark ? 'rgba(255,255,255,0.35)' : 'rgba(0,0,0,0.3)')
|
| 538 |
+
.attr('transform', `rotate(-90, ${groupLabelX}, ${cy})`)
|
| 539 |
+
.text(text);
|
| 540 |
+
|
| 541 |
+
// Hit area for the rotated text
|
| 542 |
+
const halfH = (DCLM_COUNT * cellH) / 2;
|
| 543 |
+
labelG.append('rect')
|
| 544 |
+
.attr('x', 0).attr('y', cy - halfH)
|
| 545 |
+
.attr('width', 24).attr('height', halfH * 2)
|
| 546 |
+
.attr('fill', 'transparent');
|
| 547 |
|
| 548 |
+
labelG.on('mouseenter', function() {
|
| 549 |
+
tip.innerHTML = `<div style="font-weight:700;font-size:13px;margin-bottom:4px;">${text} Score</div><div style="font-size:12px;color:var(--muted-color);line-height:1.45;">${GROUP_DESC[text]}</div>`;
|
| 550 |
+
tip.style.opacity = '1';
|
| 551 |
+
})
|
| 552 |
+
.on('mousemove', function(ev) {
|
| 553 |
+
const [mx, my] = d3.pointer(ev, container);
|
| 554 |
+
tip.style.transform = `translate(${Math.round(mx + 12)}px,${Math.round(my + 14)}px)`;
|
| 555 |
+
})
|
| 556 |
+
.on('mouseleave', function() {
|
| 557 |
+
tip.style.opacity = '0';
|
| 558 |
+
tip.style.transform = 'translate(-9999px,-9999px)';
|
| 559 |
+
});
|
| 560 |
});
|
| 561 |
+
}
|
| 562 |
|
| 563 |
// --- Tooltip interactions ---
|
| 564 |
cells.on('mouseenter', function(ev, d) {
|
|
|
|
| 616 |
<span class="item"><span class="swatch" style="background:${sw(0)};"></span><span>ρ = 0</span></span>
|
| 617 |
<span class="item"><span class="swatch" style="background:${sw(0.3)};"></span><span>ρ = +0.3</span></span>
|
| 618 |
<span class="item"><span class="swatch" style="background:${sw(0.6)};"></span><span>ρ = +0.6</span></span>
|
| 619 |
+
<span style="display:block;width:100%;margin-top:4px;font-size:11px;color:var(--muted-color);">*** p<0.001 ** p<0.01 * p<0.05</span>
|
| 620 |
</div>`;
|
| 621 |
container.appendChild(legend);
|
| 622 |
}
|
app/src/content/embeds/score-shift.html
CHANGED
|
@@ -172,6 +172,7 @@
|
|
| 172 |
|
| 173 |
function render() {
|
| 174 |
const width = container.clientWidth || 800;
|
|
|
|
| 175 |
const height = Math.max(420, Math.round(width / 1.8));
|
| 176 |
svg.attr('width', width).attr('height', height);
|
| 177 |
const iw = width - margin.left - margin.right;
|
|
@@ -183,16 +184,16 @@
|
|
| 183 |
const diffKey = currentMode === 'dclm' ? 'dclmDiff' : 'eduDiff';
|
| 184 |
|
| 185 |
// Three column positions
|
| 186 |
-
const colPad = Math.max(50, iw * 0.08);
|
| 187 |
const colX = [
|
| 188 |
margin.left + colPad,
|
| 189 |
margin.left + iw / 2,
|
| 190 |
width - margin.right - colPad
|
| 191 |
];
|
| 192 |
const colLabels = [
|
| 193 |
-
`Input ${mode.label}`,
|
| 194 |
-
`Output ${mode.label}`,
|
| 195 |
-
'agg_score_macro'
|
| 196 |
];
|
| 197 |
|
| 198 |
// Scales for each column (all vertical, higher = better at top)
|
|
@@ -228,7 +229,7 @@
|
|
| 228 |
|
| 229 |
// Ticks
|
| 230 |
const scale = scales[ci];
|
| 231 |
-
const ticks = scale.ticks(6);
|
| 232 |
const fmt = ci === 2 ? d3.format('.3f') : d3.format('.2f');
|
| 233 |
ticks.forEach(t => {
|
| 234 |
const y = scale(t);
|
|
@@ -239,7 +240,7 @@
|
|
| 239 |
gGrid.append('text')
|
| 240 |
.attr('x', cx - 8).attr('y', y)
|
| 241 |
.attr('text-anchor', 'end').attr('dominant-baseline', 'central')
|
| 242 |
-
.attr('fill', 'var(--tick-color)').attr('font-size', '12px')
|
| 243 |
.text(fmt(t));
|
| 244 |
});
|
| 245 |
|
|
@@ -247,7 +248,7 @@
|
|
| 247 |
gGrid.append('text')
|
| 248 |
.attr('x', cx).attr('y', margin.top - 12)
|
| 249 |
.attr('text-anchor', 'middle').attr('fill', 'var(--text-color)')
|
| 250 |
-
.attr('font-size', '14px').attr('font-weight', '700')
|
| 251 |
.text(colLabels[ci]);
|
| 252 |
});
|
| 253 |
|
|
|
|
| 172 |
|
| 173 |
function render() {
|
| 174 |
const width = container.clientWidth || 800;
|
| 175 |
+
const isMobile = width < 640;
|
| 176 |
const height = Math.max(420, Math.round(width / 1.8));
|
| 177 |
svg.attr('width', width).attr('height', height);
|
| 178 |
const iw = width - margin.left - margin.right;
|
|
|
|
| 184 |
const diffKey = currentMode === 'dclm' ? 'dclmDiff' : 'eduDiff';
|
| 185 |
|
| 186 |
// Three column positions
|
| 187 |
+
const colPad = isMobile ? Math.max(18, iw * 0.04) : Math.max(50, iw * 0.08);
|
| 188 |
const colX = [
|
| 189 |
margin.left + colPad,
|
| 190 |
margin.left + iw / 2,
|
| 191 |
width - margin.right - colPad
|
| 192 |
];
|
| 193 |
const colLabels = [
|
| 194 |
+
isMobile ? 'Input' : `Input ${mode.label}`,
|
| 195 |
+
isMobile ? 'Output' : `Output ${mode.label}`,
|
| 196 |
+
isMobile ? 'Macro' : 'agg_score_macro'
|
| 197 |
];
|
| 198 |
|
| 199 |
// Scales for each column (all vertical, higher = better at top)
|
|
|
|
| 229 |
|
| 230 |
// Ticks
|
| 231 |
const scale = scales[ci];
|
| 232 |
+
const ticks = scale.ticks(isMobile ? 4 : 6);
|
| 233 |
const fmt = ci === 2 ? d3.format('.3f') : d3.format('.2f');
|
| 234 |
ticks.forEach(t => {
|
| 235 |
const y = scale(t);
|
|
|
|
| 240 |
gGrid.append('text')
|
| 241 |
.attr('x', cx - 8).attr('y', y)
|
| 242 |
.attr('text-anchor', 'end').attr('dominant-baseline', 'central')
|
| 243 |
+
.attr('fill', 'var(--tick-color)').attr('font-size', isMobile ? '10px' : '12px')
|
| 244 |
.text(fmt(t));
|
| 245 |
});
|
| 246 |
|
|
|
|
| 248 |
gGrid.append('text')
|
| 249 |
.attr('x', cx).attr('y', margin.top - 12)
|
| 250 |
.attr('text-anchor', 'middle').attr('fill', 'var(--text-color)')
|
| 251 |
+
.attr('font-size', isMobile ? '11px' : '14px').attr('font-weight', '700')
|
| 252 |
.text(colLabels[ci]);
|
| 253 |
});
|
| 254 |
|