deck: port approved 'The problem' composition — four challenges + outputs rail from Marts + ThothII right with drawn arrow + AI circuit-brain medallions (.brain-ai, no clash with slide-3 .brain)

This commit is contained in:
Codex
2026-09-07 20:42:05 +02:00
parent 197c165a0a
commit da60b6af36
3 changed files with 110 additions and 12 deletions
+37
View File
@@ -94,6 +94,43 @@
.arit .code .en::before { content: 'EN'; display: inline-block; margin-right: 8px; padding: 2px 6px; .arit .code .en::before { content: 'EN'; display: inline-block; margin-right: 8px; padding: 2px 6px;
border-radius: 3px; background: var(--bordeaux); color: #fdfcfc; border-radius: 3px; background: var(--bordeaux); color: #fdfcfc;
font: 700 8.5px/1 var(--sans); letter-spacing: .1em; } font: 700 8.5px/1 var(--sans); letter-spacing: .1em; }
/* ---------- slide "The problem": challenges + outputs rail + ThothII right ---------- */
.arit.problem .sbody { padding-top: 20px; padding-bottom: 14px; }
.arit.problem .kicker { margin-bottom: 10px; }
.arit.problem .quote { margin: 0 0 10px; padding: 12px 22px 10px 64px; font-size: 16.5px; }
.arit.problem .tr-grid .en { font-size: 16.5px; }
.arit.problem .stage { padding: 11px 10px; }
.arit.problem .stage b { font-size: 13px; text-transform: uppercase; }
.arit.problem .stage span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .02em; }
.arit.problem .stage.hot { background: #fdf1f2; border-color: var(--bordeaux); }
.arit .brain-ai { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
border-radius: 9999px; background: #fff; border: 1.5px solid var(--bordeaux); }
.arit .brain-ai svg { width: 24px; height: 24px; color: var(--bordeaux); }
.arit.problem .stage .brain-ai { margin-top: 3px; }
.arit.problem .midrow { display: flex; gap: 28px; margin-top: 8px; align-items: flex-start; }
.arit.problem .concepts { flex: 1; min-width: 0; }
.arit .concepts .lbl, .arit .rail .lbl { display: block; font: 700 10px/1 var(--mono); letter-spacing: .14em;
text-transform: uppercase; color: var(--bordeaux); margin: 0 0 5px; }
.arit .citem { display: flex; gap: 12px; align-items: baseline; padding: 5px 0; border-bottom: 1px solid var(--line); }
.arit .citem:last-child { border-bottom: none; }
.arit .citem .n { font: 700 11px/1 var(--mono); color: var(--bordeaux); }
.arit .citem b { font: 700 12.5px/1.3 var(--sans); color: var(--ink); text-transform: uppercase; letter-spacing: .03em; }
.arit .citem span.d { font: 400 11px/1.4 var(--sans); color: var(--ink-muted); margin-left: 8px; }
.arit .railwrap { position: relative; display: flex; justify-content: flex-end; }
.arit .conn-drop, .arit .t-conn { position: absolute; width: 2px; background: var(--bordeaux); }
.arit .conn-elbow { position: absolute; height: 2px; background: var(--bordeaux); }
.arit .t-head { position: absolute; width: 0; height: 0; border: 5px solid transparent;
border-bottom: 7px solid var(--bordeaux); transform: translateX(-50%); }
.arit .rail { width: 520px; border-left: 2px solid var(--bordeaux); padding-top: 12px; }
.arit .rail .row { display: flex; align-items: center; gap: 12px; padding: 5px 14px 5px 16px; position: relative; }
.arit .rail .row::before { content: ''; position: absolute; left: -2px; top: 50%; width: 14px; height: 2px; background: var(--bordeaux); }
.arit .rail .row .oicon { flex: 0 0 26px; width: 26px; height: 26px; color: var(--bordeaux); display: block; }
.arit .rail .row b { font: 700 13px/1.2 var(--sans); color: var(--ink); text-transform: uppercase; letter-spacing: .03em; }
.arit .rail .row span.d { font: 400 11px/1.3 var(--sans); color: var(--ink-muted); }
.arit.problem .thoth-wrap { position: relative; justify-content: flex-end; margin-top: 10px; }
.arit.problem .thoth-box { padding: 8px 14px; font-size: 11px; text-transform: uppercase; letter-spacing: .02em; }
.arit.problem .thoth-box .brain-ai { margin-right: 9px; vertical-align: middle; }
.arit .quote small { display: block; margin-top: 6px; font: 600 11px/1.4 var(--sans); font-style: normal; .arit .quote small { display: block; margin-top: 6px; font: 600 11px/1.4 var(--sans); font-style: normal;
letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); } letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); }
+70 -9
View File
@@ -5,7 +5,7 @@
<title>AritmoLab — Role of AI in the Analysis of Unstructured Clinical Databases</title> <title>AritmoLab — Role of AI in the Analysis of Unstructured Clinical Databases</title>
<link rel="stylesheet" href="vendor/reveal/dist/reveal.css"> <link rel="stylesheet" href="vendor/reveal/dist/reveal.css">
<link rel="stylesheet" href="fonts.css?v=8"> <link rel="stylesheet" href="fonts.css?v=8">
<link rel="stylesheet" href="deck.css?v=28"> <link rel="stylesheet" href="deck.css?v=29">
</head> </head>
<body> <body>
<div class="reveal"><div class="slides"> <div class="reveal"><div class="slides">
@@ -152,7 +152,7 @@
</section> </section>
<section class="arit center-v"> <section class="arit center-v problem">
<header class="head"> <header class="head">
<img src="logo.png" alt=""> <img src="logo.png" alt="">
<span class="head-org">AritmoLab · Policlinico San Donato</span> <span class="head-org">AritmoLab · Policlinico San Donato</span>
@@ -168,23 +168,42 @@
<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="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> <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>
<small>One sentence from a discharge letter (example) — diagnosis, history and test outcome, all in free text</small>
</div> </div>
<div class="pipeline"> <div class="pipeline" id="pipeline">
<div class="stage"><b>Sources</b><span>Cardioref · Genetic data<br>Omics Portal · ECG</span></div> <div class="stage"><b>Sources</b><span>Cardioref · Genetic data<br>Omics Portal · ECG</span></div>
<div class="arrow">→</div> <div class="arrow">→</div>
<div class="stage"><b>Staging</b><span>raw replica</span></div> <div class="stage"><b>Staging</b><span>raw replica</span></div>
<div class="arrow">→</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="stage ai"><b>Integration</b><span>3NF · text mining</span><span class="brain-ai"><svg viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4 C11 2 5.5 4 6 8.5 C2.5 10 2 14.5 4.5 17 C2.5 20 4 24.5 8 25 C9 28 14 29.5 16 27"/><path d="M16 4 C21 2 26.5 4 26 8.5 C29.5 10 30 14.5 27.5 17 C29.5 20 28 24.5 24 25 C23 28 18 29.5 16 27"/><path d="M16 4.5 V26.5"/><path d="M16 10 h4.5"/><circle cx="23" cy="10" r="1.7" fill="currentColor" stroke="none"/><path d="M16 15.5 h-4.5"/><circle cx="8.5" cy="15.5" r="1.7" fill="currentColor" stroke="none"/><path d="M16 21 h4.5"/><circle cx="23" cy="21" r="1.7" fill="currentColor" stroke="none"/></svg></span></div>
<div class="arrow">→</div> <div class="arrow">→</div>
<div class="stage"><b>Data Warehouse</b><span>star schema</span></div> <div class="stage"><b>Data Warehouse</b><span>star schema</span></div>
<div class="arrow">→</div> <div class="arrow">→</div>
<div class="stage"><b>Marts</b><span>dbt · Superset</span></div> <div class="stage hot" id="marts"><b>Marts</b><span>dbt · Superset</span></div>
</div> </div>
<div class="thoth-wrap"> <div class="midrow">
<div class="concepts">
<div class="lbl">four challenges to face · the answers come next</div>
<div class="citem"><span class="n">01</span><div><b>Volume without structure</b><span class="d">twenty years of records locked in free-text columns</span></div></div>
<div class="citem"><span class="n">02</span><div><b>Ambiguous language</b><span class="d">negation · family history · bilingual shorthand</span></div></div>
<div class="citem"><span class="n">03</span><div><b>No shared ontology</b><span class="d">every system names conditions its own way</span></div></div>
<div class="citem"><span class="n">04</span><div><b>Proving reliability</b><span class="d">extraction must be demonstrably correct</span></div></div>
</div>
<div class="railwrap" id="railwrap">
<div class="conn-drop" id="conn-drop"></div>
<div class="conn-elbow" id="conn-elbow"></div>
<div class="rail" id="rail">
<div class="lbl">outputs of the datamarts</div>
<div class="row"><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><b>Dashboards</b><span class="d">clinical review on Superset</span></div>
<div class="row"><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><b>Machine Learning</b><span class="d">cohort tables for model training</span></div>
<div class="row"><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><b>Predictive Statistics</b><span class="d">outcomes &amp; risk analysis</span></div>
</div>
</div>
</div>
<div class="thoth-wrap" id="thothwrap">
<div class="t-conn" id="t-conn"></div>
<div class="t-head" id="t-head"></div>
<div class="thoth-col"> <div class="thoth-col">
<div class="thoth-arrow">↑</div> <div class="thoth-box"><span class="brain-ai"><svg viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4 C11 2 5.5 4 6 8.5 C2.5 10 2 14.5 4.5 17 C2.5 20 4 24.5 8 25 C9 28 14 29.5 16 27"/><path d="M16 4 C21 2 26.5 4 26 8.5 C29.5 10 30 14.5 27.5 17 C29.5 20 28 24.5 24 25 C23 28 18 29.5 16 27"/><path d="M16 4.5 V26.5"/><path d="M16 10 h4.5"/><circle cx="23" cy="10" r="1.7" fill="currentColor" stroke="none"/><path d="M16 15.5 h-4.5"/><circle cx="8.5" cy="15.5" r="1.7" fill="currentColor" stroke="none"/><path d="M16 21 h4.5"/><circle cx="23" cy="21" r="1.7" fill="currentColor" stroke="none"/></svg></span>ThothII — natural-language → SQL over the DWH, builds the final datamarts</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>
</div> </div>
@@ -527,6 +546,48 @@
document.querySelectorAll('.arit .band select.jump').forEach((s) => { s.selectedIndex = idx; s.blur(); }); document.querySelectorAll('.arit .band select.jump').forEach((s) => { s.selectedIndex = idx; s.blur(); });
}); });
// slide "The problem": rail drops from Marts center, ThothII arrow rises to Marts.
// Reveal scales the canvas — all rect offsets are divided by the current scale.
function alignProblem() {
const pipe = document.getElementById('pipeline');
if (!pipe || !pipe.closest('section').classList.contains('present')) return;
const s = Reveal.getScale() || 1;
const pr = pipe.getBoundingClientRect();
const marts = document.getElementById('marts').getBoundingClientRect();
const rail = document.getElementById('rail').getBoundingClientRect();
const rwrap = document.getElementById('railwrap').getBoundingClientRect();
const drop = document.getElementById('conn-drop');
const elbow = document.getElementById('conn-elbow');
const cx = (marts.left + marts.width / 2 - rwrap.left) / s;
const railLeft = (rail.left - rwrap.left) / s;
const railTop = (rail.top - rwrap.top) / s;
drop.style.left = (cx - 1) + 'px';
drop.style.top = ((marts.top - rwrap.top) / s) + 'px';
drop.style.height = Math.max(0, railTop - (marts.top - rwrap.top) / s) + 'px';
elbow.style.left = railLeft + 'px';
elbow.style.width = Math.max(0, cx - railLeft) + 'px';
elbow.style.top = (railTop - 1) + 'px';
const twrap = document.getElementById('thothwrap');
const box = twrap.querySelector('.thoth-box');
const tr = twrap.getBoundingClientRect();
const br = box.getBoundingClientRect();
const conn = document.getElementById('t-conn');
const head = document.getElementById('t-head');
const x = tr.width / s - 10;
const top = (pr.bottom - tr.top) / s + 2;
const boxTop = (br.top - tr.top) / s;
conn.style.left = x + 'px';
conn.style.top = top + 'px';
conn.style.height = Math.max(0, boxTop - top) + 'px';
head.style.left = x + 'px';
head.style.top = (top - 7) + 'px';
}
addEventListener('load', alignProblem);
addEventListener('resize', alignProblem);
Reveal.on('slidechanged', alignProblem);
Reveal.on('ready', alignProblem);
if (document.fonts && document.fonts.ready) document.fonts.ready.then(alignProblem);
const AI_CONTRIBS = { const AI_CONTRIBS = {
ingestion: { ingestion: {
title: 'The mappings', title: 'The mappings',
+3 -3
View File
@@ -28,16 +28,16 @@
</head> </head>
<body> <body>
<h1>Deck overview — 14 slides · AritmoLab</h1> <h1>Deck overview — 14 slides · AritmoLab</h1>
<p class="note">Live previews of <b>/deck/index.html</b> · slide 04 shows the old deck layout: the approved new composition is in <b>slide05-outputs.html</b> (not yet ported).</p> <p class="note">Live previews of <b>/deck/index.html</b> · all 14 slides as committed on <b>feat/ai-etl-presentation</b>.</p>
<div class="grid" id="grid"></div> <div class="grid" id="grid"></div>
<script> <script>
const TITLES = ['Title', 'Where we started', 'What we wanted to build', 'The problem', const TITLES = ['Title', 'Where we started', 'What we wanted to build', 'The problem',
'What the text miner reads', 'Hard problems of clinical NLP', 'The clinical ontology', 'What the text miner reads', 'Hard problems of clinical NLP', 'The clinical ontology',
'Trust the text', 'AritmoLab today', 'All good? Not yet', 'ThothII', 'A tour of ThothII', 'Trust the text', 'AritmoLab today', 'All good? Not yet', 'ThothII', 'A tour of ThothII',
'From datamarts to models', 'Thank you']; 'From datamarts to models', 'Thank you'];
const STATUS = ['FINAL', 'FINAL', 'FINAL', 'NEW IN PROTOTYPE', 'REFINED', 'REFINED', 'REFINED', 'REFINED', const STATUS = ['FINAL', 'FINAL', 'FINAL', 'REFINED', 'REFINED', 'REFINED', 'REFINED', 'REFINED',
'DRAFT', 'DRAFT', 'DRAFT', 'DRAFT', 'DRAFT', 'DRAFT']; 'DRAFT', 'DRAFT', 'DRAFT', 'DRAFT', 'DRAFT', 'DRAFT'];
const CLS = ['final', 'final', 'final', 'proto', 'refined', 'refined', 'refined', 'refined', const CLS = ['final', 'final', 'final', 'refined', 'refined', 'refined', 'refined', 'refined',
'draft', 'draft', 'draft', 'draft', 'draft', 'draft']; 'draft', 'draft', 'draft', 'draft', 'draft', 'draft'];
const grid = document.getElementById('grid'); const grid = document.getElementById('grid');
TITLES.forEach((t, i) => { TITLES.forEach((t, i) => {