當你駕駛一輛頂級跑車時,如果儀表板上顯示的不是「時速 120 km/h」或「引擎過熱警示紅燈」,而是幾萬行感測器傳回來的原始電壓數字(如 0.0023V, 12.4V),你一定會開到崩潰!
駕駛需要的是能 「在 0.1 秒內做出直覺反應」 的圖形介面,而不是一堆無意義的原始訊號。
在醫院的臨床診斷中也是一模一樣的道理!
今天,正式進入如何使用 React 與 Recharts 圖表庫,把硬核的 AI 數據包包裝成 「0.5 秒就能看懂」 的智慧醫療診斷儀表板!
為了讓忙碌的臨床醫師能在最短時間內掌握關鍵資訊,我們的 React 前端儀表板設計了三大核心視覺化元件:
RadarChart 元件,將 18 類特徵(如 RNA 剪接 Splicing、基因表達量 CAGE、染色質開放度 ATAC 與演化保守性等)映射到雷達圖的 18 個軸線上。Splicing 軸線就會跳出一個巨大的尖銳突起!醫師只要花 0.5 秒 掃過圖形,就能立刻說出:「這個變異是剪接壞掉了!」| 視覺化元件 | 傳統資料呈現方式 | React 智慧儀表板呈現方式 | 醫師獲取資訊時間 |
|---|---|---|---|
| 機制辨析 | 幾千行的原始 JSON 數據包。 | 特徵貢獻雷達圖(突起軸線即代表機制)。 | ⚡ 0.5 秒(看圖形突起) |
| 軌跡比對 | 幾千個浮點數陣列數字。 | 雙色波形圖(藍線正常 vs. 紅線突變波峰)。 | ⚡ 1 秒(看紅線波峰) |
| 臨床判決 | 手動翻閱 ACMG 幾十頁判決指引。 | 🔴 醒目燈號卡片 + Gemini 白話摘要卡。 | ⚡ 1 秒(看燈號與白話文字) |
VariantDashboard.jsx)現在,我們來看看如何在前端 React 專案中寫出這個可互動的診斷儀表板元件 VariantDashboard.jsx:
import React from 'react';
import { Radar, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid } from 'recharts';
// 模擬從 Python 後端 API 傳來的 JSON 數據包 (以六週大幼兒 DNM1 變異為例)
const mockApiResponse = {
variantId: "chr9:128225994:G:A",
gene: "DNM1",
acmgVerdict: "Pathogenic", // 🔴 致病
aviScore: 24.7,
llmSummary: "此變異 AVI 評分為 24.7,強烈受大腦神經元隱藏剪接驅動 (貢獻度 69%),極可能引發 Exon 10a 異常拼接。",
radarData: [
{ feature: 'Splicing', score: 85 },
{ feature: 'CAGE (Brain)', score: 30 },
{ feature: 'ATAC (Neuron)', score: 45 },
{ feature: 'H3K4me3', score: 20 },
{ feature: 'Evolution', score: 15 },
{ feature: 'Exon Coding', score: 10 }
],
trackData: [
{ pos: -100, ref: 0.01, alt: 0.01 },
{ pos: -50, ref: 0.02, alt: 0.02 },
{ pos: 0, ref: 0.02, alt: 0.85 }, // 🚨 突變點引發波峰狂飙!
{ pos: 50, ref: 0.01, alt: 0.03 },
{ pos: 100, ref: 0.01, alt: 0.01 }
]
};
export default function VariantDashboard() {
const data = mockApiResponse;
return (
<div className="p-6 bg-slate-900 text-white min-h-screen">
{/* 1. 頂部 ACMG 燈號與白話摘要卡片 */}
<div className="mb-6 p-4 rounded-xl bg-slate-800 border border-red-500/50 shadow-lg">
<div className="flex items-center gap-3 mb-2">
<span className="px-3 py-1 rounded-full text-sm font-bold bg-red-600 text-white animate-pulse">
🔴 ACMG: {data.acmgVerdict} (致病)
</span>
<h2 className="text-xl font-bold">{data.gene} ({data.variantId})</h2>
<span className="text-slate-400 text-sm">AVI Score: {data.aviScore} / 30</span>
</div>
<p className="text-slate-300 text-sm leading-relaxed bg-slate-900/60 p-3 rounded-lg border border-slate-700">
💡 <strong>Gemini AI 臨床摘要:</strong> {data.llmSummary}
</p>
</div>
{/* 2. 中間圖表區:左雷達圖、右波形軌跡圖 */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* 左側:特徵貢獻雷達圖 */}
<div className="p-4 rounded-xl bg-slate-800 border border-slate-700">
<h3 className="text-md font-bold mb-4 text-cyan-400">📊 特徵貢獻雷達圖 (Feature Attribution)</h3>
<div className="h-64">
<ResponsiveContainer width="100%" height="100%">
<RadarChart data={data.radarData}>
<PolarGrid stroke="#475569" />
<PolarAngleAxis dataKey="feature" stroke="#94a3b8" />
<PolarRadiusAxis angle={30} domain={} stroke="#475569" />
<Radar name="Impact Weight" dataKey="score" stroke="#06b6d4" fill="#0891b2" fillOpacity={0.6} />
</RadarChart>
</ResponsiveContainer>
</div>
</div>
{/* 右側:多模態軌跡波形圖 */}
<div className="p-4 rounded-xl bg-slate-800 border border-slate-700">
<h3 className="text-md font-bold mb-4 text-emerald-400">📈 大腦神經元 RNA 剪接軌跡波形對比</h3>
<div className="h-64">
<ResponsiveContainer width="100%" height="100%">
<LineChart data={data.trackData}>
<CartesianGrid strokeDasharray="3 3" stroke="#334155" />
<XAxis dataKey="pos" stroke="#94a3b8" />
<YAxis domain={} stroke="#94a3b8" />
<Tooltip contentStyle={{ backgroundColor: '#1e293b', borderColor: '#475569' }} />
<Line type="monotone" dataKey="ref" stroke="#3b82f6" name="Ref (正常)" strokeWidth={2} />
<Line type="monotone" dataKey="alt" stroke="#ef4444" name="Alt (突變)" strokeWidth={3} />
</LineChart>
</ResponsiveContainer>
</div>
</div>
</div>
</div>
);
}
這段 React 程式碼直接將原本艱深難懂的生醫大數據,渲染成一個具備科技感、直覺且充滿臨床洞察力的「智慧醫療儀表板」!