Files
ThothII/presentation/prototype/slide05-outputs.html
T

290 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<!-- PROTOTYPE (throwaway) — Three variants of the "outputs from the datamarts" zone
for deck slide "The problem". Switchable via ?variant=A|B|C, floating switcher.
Question: how should Dashboards / Machine Learning / Predictive Statistics
be represented as the three outputs of the Marts stage? -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>PROTOTYPE · Slide “The problem” — outputs from the datamarts (3 options)</title>
<link rel="stylesheet" href="/deck/fonts.css">
<style>
:root {
--bordeaux: #cb333b; --bordeaux-deep: #8f1204; --bordeaux-tint: #f4dfe1;
--surface: #fdfcfc; --surface-alt: #f6f5f5; --surface-sunken: #ecebeb;
--ink: #2a2426; --ink-muted: #6b6568;
--line: #e3e0e1; --line-strong: #c9c5c6;
--sans: 'Source Sans 3', system-ui, sans-serif;
--display: 'Source Serif 4', Georgia, serif;
--mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}
* { box-sizing: border-box; }
body { margin: 0; background: #e9e7e7; font-family: var(--sans); padding: 26px 0 90px; }
.proto-head { text-align: center; margin: 0 0 14px; }
.proto-head b { font: 700 12px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--bordeaux); }
.proto-head span { display: block; margin-top: 6px; font: 400 13px/1.4 var(--sans); color: var(--ink-muted); }
/* ---- slide frame (deck-like, 1200×690) ---- */
.frame { width: 1200px; height: 690px; margin: 0 auto; background: var(--surface);
display: flex; flex-direction: column; box-shadow: 0 8px 30px rgba(42,36,38,.18); overflow: hidden; }
.head { flex: 0 0 74px; display: flex; align-items: center; justify-content: space-between;
padding: 0 40px; border-bottom: 1px solid var(--line); }
.head img { height: 54px; display: block; }
.head-org { font: 700 11px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-muted); }
.band { flex: 0 0 42px; display: flex; align-items: center; justify-content: space-between;
padding: 0 40px; background: var(--bordeaux); color: var(--surface); }
.band b { font: 700 12.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; }
.sbody { flex: 1; min-height: 0; display: flex; flex-direction: column;
padding: 20px 48px 14px; text-align: left; }
.foot { flex: 0 0 30px; display: flex; align-items: center; justify-content: space-between; gap: 24px;
padding: 0 40px; border-top: 1px solid var(--line);
font: 600 9.5px/1.4 var(--sans); letter-spacing: .03em; color: var(--ink-muted); }
.kicker { font: 700 11.5px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase; color: var(--bordeaux); margin-bottom: 10px; }
h2 { font: 700 27px/1.15 var(--sans); letter-spacing: -.01em; color: var(--ink); margin: 0 0 10px; }
.quote { position: relative; margin: 0 0 14px; padding: 14px 22px 11px 64px; border: 1px solid var(--line);
background: var(--surface-alt); border-radius: 8px;
font: italic 400 16.5px/1.5 var(--display); color: var(--ink); }
.quote::before { content: '\201C'; position: absolute; left: 18px; top: 6px;
font: 700 44px/1 var(--display); color: var(--bordeaux); }
.tr-grid { display: grid; grid-template-columns: 1.12fr 1fr; gap: 22px; align-items: center; }
.tr-grid .it, .tr-grid .en { margin: 0; }
.tr-grid .en { padding-left: 18px; border-left: 1px solid var(--line-strong);
font: 400 12.5px/1.55 var(--sans); color: var(--bordeaux-deep); }
.en-tag { display: inline-block; margin-right: 7px; padding: 2px 7px; border-radius: 4px;
background: var(--bordeaux); color: #fdfcfc; font: 700 9px/1 var(--sans); letter-spacing: .12em; vertical-align: 1px; }
.quote small { display: block; margin-top: 5px; font: 600 9.5px/1.4 var(--sans); font-style: normal;
letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); }
.pipeline { display: flex; align-items: stretch; gap: 10px; }
.stage { flex: 1; padding: 10px 8px; text-align: center; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-alt); }
.stage b { display: block; font: 700 12.5px/1.2 var(--sans); margin-bottom: 3px; }
.stage span { display: block; font: 400 10.5px/1.35 var(--sans); color: var(--ink-muted); }
.stage .tag { display: inline-block; margin-top: 4px; padding: 2px 9px; border-radius: 9999px;
background: var(--bordeaux); color: #fdfcfc; font: 700 8.5px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; }
.stage.ai { background: var(--bordeaux-tint); border-color: var(--bordeaux); }
.arrow { align-self: center; color: var(--line-strong); font: 700 17px/1 var(--sans); }
.stage.hot { background: #fdf1f2; border-color: var(--bordeaux); }
.thoth-wrap { display: flex; justify-content: flex-end; margin-top: 12px; }
.thoth-wrap.left { justify-content: flex-start; }
.thoth-col { width: 500px; text-align: center; }
.thoth-arrow { color: var(--line-strong); font: 700 15px/1 var(--sans); margin: 1px 0; }
.thoth-box { border: 1px solid var(--bordeaux); border-radius: 8px; padding: 9px 14px;
background: var(--surface-alt); font: 600 11.5px/1.4 var(--sans); }
.thoth-box .tag { display: inline-block; margin-right: 7px; padding: 2px 9px; border-radius: 9999px;
background: var(--bordeaux); color: #fdfcfc; font: 700 8.5px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; }
/* ---- outputs icons ---- */
.oicon { width: 34px; height: 34px; color: var(--bordeaux); display: block; }
.oicon * { vector-effect: non-scaling-stroke; }
/* ---- variant A: branch tree from Marts ---- */
.fanwrap { display: flex; justify-content: flex-end; margin-top: 0; }
.fan { width: 58%; position: relative; padding-top: 16px; }
.fan .drop { position: absolute; top: -6px; right: 128px; width: 2px; height: 22px; background: var(--bordeaux); }
.fan .rail { height: 2px; background: var(--bordeaux); margin: 0 60px 0 40px; position: relative; }
.fan .nodes { display: flex; margin-top: 0; }
.fan .node { flex: 1; text-align: center; position: relative; padding-top: 14px; }
.fan .node::before { content: ''; position: absolute; top: 0; left: 50%; width: 2px; height: 14px;
background: var(--bordeaux); transform: translateX(-50%); }
.fan .node .oicon { margin: 0 auto 5px; }
.fan .node b { display: block; font: 700 13px/1.2 var(--sans); color: var(--ink); }
.fan .node span { display: block; font: 400 10.5px/1.35 var(--sans); color: var(--ink-muted); margin-top: 2px; }
/* ---- variant B: outputs band ---- */
.oband { margin-top: 12px; }
.oband .lbl { font: 700 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
color: var(--bordeaux); text-align: center; margin-bottom: 8px; }
.oband .tiles { display: flex; gap: 12px; }
.oband .tile { flex: 1; display: flex; align-items: center; gap: 12px; padding: 11px 14px;
border: 1px solid var(--line); border-radius: 8px; background: var(--surface-alt); }
.oband .tile .ic { flex: 0 0 44px; height: 44px; border-radius: 9999px; background: var(--bordeaux-tint);
display: flex; align-items: center; justify-content: center; }
.oband .tile .ic .oicon { width: 26px; height: 26px; }
.oband .tile b { display: block; font: 700 13.5px/1.2 var(--sans); color: var(--ink); }
.oband .tile span { display: block; margin-top: 2px; font: 400 11px/1.35 var(--sans); color: var(--ink-muted); }
/* ---- variant C: maturity rail ---- */
.railwrap { display: flex; justify-content: flex-end; margin-top: 10px; }
.rail { width: 560px; border-left: 2px solid var(--bordeaux); padding: 2px 0 2px 0; }
.rail .row { display: flex; align-items: center; gap: 12px; padding: 7px 14px 7px 16px; position: relative; }
.rail .row::before { content: ''; position: absolute; left: 0; top: 50%; width: 14px; height: 2px; background: var(--bordeaux); }
.rail .row .oicon { flex: 0 0 26px; width: 26px; height: 26px; }
.rail .row b { font: 700 13.5px/1.2 var(--sans); color: var(--ink); }
.rail .row span.d { font: 400 11px/1.3 var(--sans); color: var(--ink-muted); }
.rail .row .st { margin-left: auto; font: 700 9px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase;
padding: 3px 9px; border-radius: 9999px; }
.rail .row.today .st { background: var(--bordeaux); color: #fdfcfc; }
.rail .row.next { border: 1px dashed var(--line-strong); border-radius: 8px; background: transparent; }
.rail .row.next .oicon { opacity: .55; }
.rail .row.next .st { border: 1px solid var(--line-strong); color: var(--ink-muted); }
.rail .lbl { font: 700 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
color: var(--bordeaux); margin: 0 0 6px 16px; }
/* ---- variant switcher (prototype chrome) ---- */
.switch { position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 50;
display: flex; align-items: center; gap: 10px; background: #2a2426; color: #fdfcfc;
padding: 8px 12px; border-radius: 9999px; box-shadow: 0 6px 22px rgba(0,0,0,.35);
font: 600 12.5px/1 var(--sans); }
.switch button { border: none; background: #4a4345; color: #fdfcfc; width: 28px; height: 28px;
border-radius: 9999px; font: 700 14px/1 var(--sans); cursor: pointer; }
.switch button:hover { background: var(--bordeaux); }
.caption { max-width: 1200px; margin: 12px auto 0; text-align: center;
font: 400 12.5px/1.5 var(--sans); color: var(--ink-muted); }
.caption b { color: var(--ink); }
</style>
</head>
<body>
<div class="proto-head">
<b>Prototype — slide “The problem” · outputs from the datamarts</b>
<span>Three structural options for Dashboards / Machine Learning / Predictive Statistics. Use the bar below or the arrow keys.</span>
</div>
<div class="frame">
<div class="head">
<img src="/deck/logo.png" alt="">
<span class="head-org">AritmoLab · Policlinico San Donato</span>
</div>
<div class="band"><b>The problem</b><span style="font:700 11px/1 var(--sans)">04 · The problem</span></div>
<div class="sbody">
<div class="kicker">From free text to a research platform</div>
<h2>The clinical truth lives in unstructured columns</h2>
<div class="quote">
<div class="tr-grid">
<p class="it">“Il paziente riferisce sincope ricorrente; ECG basale con sopraslivellamento ST in V1–V3; test provocativo con flecainide positivo per pattern Brugada.”</p>
<p class="en"><span class="en-tag">EN</span>“The patient reports recurrent syncope; baseline ECG with ST-segment elevation in V1–V3; flecainide provocation test positive for a Brugada pattern.”</p>
</div>
</div>
<div class="pipeline" id="pipeline">
<div class="stage"><b>Sources</b><span>Cardioref · Genetic data<br>Omics Portal · ECG</span></div>
<div class="arrow">→</div>
<div class="stage"><b>Staging</b><span>raw replica</span></div>
<div class="arrow">→</div>
<div class="stage ai"><b>Integration</b><span>3NF · text mining</span><span class="tag">AI</span></div>
<div class="arrow">→</div>
<div class="stage"><b>Data Warehouse</b><span>star schema</span></div>
<div class="arrow">→</div>
<div class="stage hot" id="marts"><b>Marts</b><span>dbt · Superset</span></div>
</div>
<div class="variant-zone"></div>
<div class="thoth-wrap" id="thothwrap">
<div class="thoth-col">
<div class="thoth-arrow">↑</div>
<div class="thoth-box"><span class="tag">AI</span>ThothII — natural-language → SQL over the DWH, builds the final datamarts</div>
</div>
</div>
</div>
<div class="foot"><span>Role of AI in the Analysis of Unstructured Clinical Databases</span><span>Dr. Marco Pancotti - MultiPhysixLab</span><span>Dr. Sara Paratico - Gruppo San Donato</span><span>San Donato Milanese, Milan, Italy · 2–3 October 2026</span><span>04 / 14</span></div>
</div>
<p class="caption" id="caption"></p>
<div class="switch">
<button id="prev" aria-label="previous variant">←</button>
<span id="label"></span>
<button id="next" aria-label="next variant">→</button>
</div>
<svg width="0" height="0" style="position:absolute">
<defs>
<g id="i-dash">
<svg class="oicon" viewBox="0 0 34 34" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
<path d="M4 29 h26"/><rect x="7" y="17" width="5" height="12" rx="1"/><rect x="15" y="9" width="5" height="20" rx="1"/><rect x="23" y="13" width="5" height="16" rx="1"/>
</svg>
</g>
<g id="i-ml">
<svg class="oicon" viewBox="0 0 34 34" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<circle cx="7" cy="7" r="2.6"/><circle cx="7" cy="27" r="2.6"/><circle cx="17" cy="17" r="3.4"/><circle cx="27" cy="7" r="2.6"/><circle cx="27" cy="27" r="2.6"/>
<path d="M9.3 8.8 L14.6 14.6"/><path d="M9.3 25.2 L14.6 19.4"/><path d="M19.4 14.6 L24.7 8.8"/><path d="M19.4 19.4 L24.7 25.2"/>
</svg>
</g>
<g id="i-pred">
<svg class="oicon" viewBox="0 0 34 34" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
<path d="M3 27 L11 19 L17 22 L23 13"/><path d="M23 13 L30 6" stroke-dasharray="3 3.4"/><circle cx="30" cy="6" r="2.2" fill="currentColor" stroke="none"/><path d="M3 31 h28" opacity=".35"/>
</svg>
</g>
</defs>
</svg>
<script>
const ICON = {
dash: document.getElementById('i-dash').innerHTML,
ml: document.getElementById('i-ml').innerHTML,
pred: document.getElementById('i-pred').innerHTML
};
const VARIANTS = {
A: {
name: 'A — Branch from Marts',
caption: '<b>A · Branch from Marts.</b> The three outputs fan out of the Marts stage as icon nodes on a connector tree: lightest visual weight, reads as “the pipeline flows on”. ThothII moves bottom-left, so left = AI reads the DWH, right = research outputs.',
html: `
<div class="fanwrap">
<div class="fan">
<div class="drop"></div>
<div class="rail"></div>
<div class="nodes">
<div class="node">${ICON.dash}<b>Dashboards</b><span>clinical review on Superset</span></div>
<div class="node">${ICON.ml}<b>Machine Learning</b><span>cohort tables for model training</span></div>
<div class="node">${ICON.pred}<b>Predictive Statistics</b><span>outcomes &amp; risk analysis</span></div>
</div>
</div>
</div>`
},
B: {
name: 'B — Products band',
caption: '<b>B · Products band.</b> A labelled full-width band under the pipeline: three equal tiles, icon in a tinted disc + name + one-liner. Reads as “the three products of the platform” — most explicit, heaviest.',
html: `
<div class="oband">
<div class="lbl">what the datamarts enable</div>
<div class="tiles">
<div class="tile"><span class="ic">${ICON.dash}</span><span><b>Dashboards</b><span>clinical review on Superset dashboards</span></span></div>
<div class="tile"><span class="ic">${ICON.ml}</span><span><b>Machine Learning</b><span>cohort tables, ready for model training</span></span></div>
<div class="tile"><span class="ic">${ICON.pred}</span><span><b>Predictive Statistics</b><span>outcomes, risk and survival analysis</span></span></div>
</div>
</div>`
},
C: {
name: 'C — Maturity rail',
caption: '<b>C · Maturity rail.</b> A rail drops from Marts into three rows that encode the roadmap: Dashboards is live today (solid), Machine Learning and Predictive Statistics are the next steps (dashed). Sets up the “what is still missing” beat later in the talk.',
html: `
<div class="railwrap">
<div class="rail">
<div class="lbl">outputs of the datamarts</div>
<div class="row today">${ICON.dash}<b>Dashboards</b><span class="d">clinical review on Superset</span><span class="st">live today</span></div>
<div class="row next">${ICON.ml}<b>Machine Learning</b><span class="d">cohort tables for model training</span><span class="st">next</span></div>
<div class="row next">${ICON.pred}<b>Predictive Statistics</b><span class="d">outcomes &amp; risk analysis</span><span class="st">next</span></div>
</div>
</div>`
}
};
const keys = Object.keys(VARIANTS);
const cur = () => {
const v = (new URLSearchParams(location.search).get('variant') || 'A').toUpperCase();
return keys.includes(v) ? v : 'A';
};
function render() {
const v = cur();
document.querySelector('.variant-zone').innerHTML = VARIANTS[v].html;
document.getElementById('label').textContent = VARIANTS[v].name;
document.getElementById('caption').innerHTML = VARIANTS[v].caption;
// ThothII placement: A and C put the outputs on the right → ThothII moves bottom-left
document.getElementById('thothwrap').classList.toggle('left', v !== 'B');
}
function cycle(dir) {
const i = keys.indexOf(cur());
const v = keys[(i + dir + keys.length) % keys.length];
const u = new URL(location);
u.searchParams.set('variant', v);
location.replace(u);
}
document.getElementById('prev').onclick = () => cycle(-1);
document.getElementById('next').onclick = () => cycle(1);
addEventListener('keydown', e => {
if (e.key === 'ArrowLeft') cycle(-1);
if (e.key === 'ArrowRight') cycle(1);
});
render();
</script>
</body>
</html>