html`<div style="
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 2.5rem;
row-gap: 0.5rem;
">
<div style="min-width:0; overflow:hidden">${viewof searchQuery}</div>
<div style="min-width:0; overflow:hidden">${viewof analysisType}</div>
<div style="min-width:0; overflow:hidden">${viewof indexGroups}</div>
<div style="min-width:0; overflow:hidden">${viewof pvalThresh}</div>
<div style="min-width:0; overflow:hidden">${viewof betaMin}</div>
<div style="min-width:0; overflow:hidden">${viewof sigHighlight}</div>
</div>`T2D Risk Alleles and Insulin Sensitivity: Association Browser
Effect sizes for T2D GWAS risk variants (Suzuki et al., Nature 2024) across 23 fasting and OGTT-derived insulin sensitivity indices, BMI-adjusted and unadjusted
Genetic variants identified in the largest genome-wide association study (GWAS) of type 2 diabetes (T2D) to date (Suzuki et al., Nature 2024, >2.5 million individuals) were tested for association with 23 insulin sensitivity indices (ISIs) derived from fasting blood measurements and oral glucose tolerance tests (OGTTs). For each variant, this browser lets you explore which ISI it associates with and in which direction, providing mechanistic insight into whether T2D risk alleles act through insulin resistance, impaired insulin secretion, or mixed pathophysiology. Analyses are presented both unadjusted and adjusted for BMI.
viewof searchQuery = Inputs.text({
label: "🔍 Search gene / rsID",
placeholder: "e.g. KCNJ11 or rs5219",
value: ""
})viewof analysisType = Inputs.radio(
["BMI-Adjusted", "BMI-Unadjusted"],
{ label: "Analysis", value: "BMI-Adjusted" }
)viewof indexGroups = Inputs.checkbox(
["Fasting", "OGTT,0-120", "OGTT,0-30-120"],
{
label: "Index Groups",
value: ["Fasting", "OGTT,0-120", "OGTT,0-30-120"]
}
)viewof pvalThresh = Inputs.range(
[0, 1],
{ label: "Max p-value", value: 1, step: 0.01, format: x => x.toFixed(2) }
)viewof betaMin = Inputs.range(
[0, 0.1],
{ label: "Min |β|", value: 0, step: 0.001, format: x => x.toFixed(3) }
){
const nVar = new Set(filtered.map(d => d.gene_snp_ra)).size;
const nGene = new Set(filtered.map(d => d.nearest_gene)).size;
const nSig = filtered.filter(d => +d.pvalue < 0.05).length;
return html`<div class="stat-block">
<div class="stat-item">
<span class="stat-num">${nVar}</span>
<span class="stat-lbl">variants</span>
</div>
<div class="stat-item">
<span class="stat-num">${nGene}</span>
<span class="stat-lbl">genes</span>
</div>
<div class="stat-item sig">
<span class="stat-num">${nSig}</span>
<span class="stat-lbl">sig. (p<0.05)</span>
</div>
</div>`;
}d3 = require("d3-array@3")
// ── Fixed IS index display order ───────────────────────────────────────────
IS_INDEX_ORDER = [
"inv-FIns", "inv-HOMA-IR", "Raynaud SI", "QUICKI", "Belfiore basal",
"inv-FIns/FGlu", "ISI basal", "Bennett SI", "Avignon SI0", "FIRI",
"inv-Ins 120", "inv-Glu 120", "ISI 120", "inv-Ins/Glu120", "Gutt Index",
"Avignon SI120", "Avignon SIM", "Stumvoll Modi", "Stumvoll Dem", "inv-IFC",
"BIGTT SI", "Matsuda", "Matsuda AUC"
]
// ── Full transposed datasets (kept for tabs needing both analyses) ──────────
rawBmi = transpose(data_bmi)
rawNoBmi = transpose(data_no_bmi)
// ── Active dataset (switches with radio button) ────────────────────────────
rawData = analysisType === "BMI-Adjusted" ? rawBmi : rawNoBmi
// ── Main filtered dataset (Heatmap + Volcano tabs) ─────────────────────────
filtered = rawData.filter(d => {
const q = searchQuery.toLowerCase().trim()
const matchSearch =
q === "" ||
(d.nearest_gene && d.nearest_gene.toLowerCase().includes(q)) ||
(d.index_variant && d.index_variant.toLowerCase().includes(q)) ||
(d.gene_snp_ra && d.gene_snp_ra.toLowerCase().includes(q))
const matchGroup = indexGroups.includes(d.index_group)
const matchPval = +d.pvalue <= pvalThresh
const matchBeta = Math.abs(+d.beta) >= betaMin
return matchSearch && matchGroup && matchPval && matchBeta
})
uniqueVariants = [...new Set(filtered.map(d => d.gene_snp_ra))]
visibleIndices = IS_INDEX_ORDER.filter(idx => {
const fasting = ["inv-FIns","inv-HOMA-IR","Raynaud SI","QUICKI","Belfiore basal",
"inv-FIns/FGlu","ISI basal","Bennett SI","Avignon SI0","FIRI"]
const ogtt2 = ["inv-Ins 120","inv-Glu 120","ISI 120","inv-Ins/Glu120","Gutt Index",
"Avignon SI120","Avignon SIM","Stumvoll Modi","Stumvoll Dem","inv-IFC"]
if (fasting.includes(idx)) return indexGroups.includes("Fasting")
if (ogtt2.includes(idx)) return indexGroups.includes("OGTT,0-120")
return indexGroups.includes("OGTT,0-30-120")
})
cellH = uniqueVariants.length <= 50 ? 18 : uniqueVariants.length <= 200 ? 12 : 8
plotH = Math.max(400, uniqueVariants.length * cellH + 140)
cellW = 36
plotW = Math.max(width, visibleIndices.length * cellW + 280)
leftMarg = uniqueVariants.length > 0
? Math.min(280, Math.max(160, Math.max(...uniqueVariants.map(s => s.length)) * 6))
: 200
// ── Inner join: variants present in BOTH analyses ──────────────────────────
joinedData = {
const nbMap = new Map(rawNoBmi.map(d => [d.gene_snp_ra + "|" + d.is_index, d]))
return rawBmi
.filter(d => nbMap.has(d.gene_snp_ra + "|" + d.is_index))
.map(d => {
const nb = nbMap.get(d.gene_snp_ra + "|" + d.is_index)
return {
nearest_gene: d.nearest_gene,
index_variant: d.index_variant,
t_2_d_risk_allele: d.t_2_d_risk_allele,
gene_snp_ra: d.gene_snp_ra,
is_index: d.is_index,
index_group: d.index_group,
beta_bmi: +d.beta,
beta_no_bmi: +nb.beta,
pval_bmi: +d.pvalue,
pval_no_bmi: +nb.pvalue,
beta_diff: +nb.beta - +d.beta
}
})
}
// Joined data with filters (min p / max |beta| across both analyses)
joinedFiltered = joinedData.filter(d => {
const q = searchQuery.toLowerCase().trim()
const matchSearch =
q === "" ||
(d.nearest_gene && d.nearest_gene.toLowerCase().includes(q)) ||
(d.index_variant && d.index_variant.toLowerCase().includes(q)) ||
(d.gene_snp_ra && d.gene_snp_ra.toLowerCase().includes(q))
const matchGroup = indexGroups.includes(d.index_group)
const matchPval = Math.min(d.pval_bmi, d.pval_no_bmi) <= pvalThresh
const matchBeta = Math.max(Math.abs(d.beta_bmi), Math.abs(d.beta_no_bmi)) >= betaMin
return matchSearch && matchGroup && matchPval && matchBeta
})
jVariants = [...new Set(joinedFiltered.map(d => d.gene_snp_ra))]
jCellH = jVariants.length <= 50 ? 18 : jVariants.length <= 200 ? 12 : 8
jPlotH = Math.max(400, jVariants.length * jCellH + 140)
jPlotW = Math.max(width, visibleIndices.length * cellW + 280)
jLeftMarg = jVariants.length > 0
? Math.min(280, Math.max(160, Math.max(...jVariants.map(s => s.length)) * 6))
: 200Plot.plot({
width: plotW,
height: plotH,
marginLeft: leftMarg,
marginBottom: 110,
marginRight: 80,
style: { background: "#fafafa", fontFamily: "system-ui, sans-serif", fontSize: "11px" },
color: {
type: "diverging", scheme: "RdBu", pivot: 0,
domain: [-0.02, 0.02], legend: true, label: "Effect size (β)", reverse: true
},
x: { domain: visibleIndices, tickRotate: -55, label: "Insulin Sensitivity Index", labelAnchor: "right" },
y: { domain: uniqueVariants, label: "Gene – Variant – Risk allele", tickSize: 0 },
marks: [
Plot.cell(filtered, {
x: "is_index", y: "gene_snp_ra", fill: d => +d.beta,
title: d => [
"Gene: " + d.nearest_gene,
"Variant: " + d.index_variant,
"Risk allele: " + d.t_2_d_risk_allele,
"IS Index: " + d.is_index + " (" + d.index_group + ")",
"β = " + (+d.beta).toFixed(5),
"p = " + (+d.pvalue).toExponential(3)
].join("\n"),
stroke: "#e0e0e0", strokeWidth: 0.4, rx: 1
}),
sigHighlight
? Plot.cell(filtered.filter(d => +d.pvalue < 0.05), {
x: "is_index", y: "gene_snp_ra",
stroke: "#111", strokeWidth: 1.5, fill: "none", rx: 1
})
: Plot.dot([], {}),
Plot.text(filtered.filter(d => +d.pvalue < 1e-4), {
x: "is_index", y: "gene_snp_ra",
text: () => "✶", fill: "white", fontSize: 9, frameAnchor: "middle"
})
]
})Inputs.table(filtered, {
columns: ["nearest_gene","index_variant","t_2_d_risk_allele","is_index","index_group","beta","pvalue"],
header: {
nearest_gene: "Gene", index_variant: "Variant (rsID)", t_2_d_risk_allele: "Risk Allele",
is_index: "IS Index", index_group: "Index Group", beta: "β (Effect Size)", pvalue: "P-value"
},
format: { beta: x => (+x).toFixed(5), pvalue: x => (+x).toExponential(3) },
sort: "pvalue", reverse: false, rows: 25
})Per-variant comparison of BMI-adjusted (🔵 blue) vs BMI-unadjusted (🟠 orange) effect sizes across all IS indices. Connecting lines show the direction of change: purple = BMI attenuates the effect (β shrinks after adjustment); green = BMI amplifies it (β grows after adjustment). Δβ = unadjusted − adjusted. Larger dots = p < 0.05.
Only variants present in both analyses are shown. Use the search/filter panel on the left to narrow variants, then pick one below.
viewof deltaSearch = Inputs.search(jVariants, {
placeholder: "Type gene name or rsID...",
label: "Filter variants"
})viewof deltaVariant = Inputs.select(
deltaSearch.length > 0 ? deltaSearch : jVariants,
{ label: "Select variant",
value: (deltaSearch.length > 0 ? deltaSearch : jVariants)[0] }
){
if (!deltaVariant || jVariants.length === 0)
return html`<p style="color:#888;padding:1rem;">No variants match current filters. Try relaxing p-value or β thresholds.</p>`
const rows = joinedFiltered.filter(d => d.gene_snp_ra === deltaVariant)
if (rows.length === 0)
return html`<p style="color:#888;padding:1rem;">Variant not in current filter set. Try relaxing p-value or beta thresholds.</p>`
const domain = visibleIndices.filter(idx => rows.some(d => d.is_index === idx)).reverse()
const paired = rows.flatMap(d => [
{ is_index: d.is_index, beta: d.beta_bmi, pvalue: d.pval_bmi, analysis: "BMI-Adjusted" },
{ is_index: d.is_index, beta: d.beta_no_bmi, pvalue: d.pval_no_bmi, analysis: "BMI-Unadjusted" }
])
return Plot.plot({
width,
height: Math.max(340, domain.length * 34 + 130),
marginLeft: 180, marginRight: 110, marginBottom: 50, marginTop: 30,
style: { fontSize: "11px" },
color: {
domain: ["BMI-Adjusted", "BMI-Unadjusted"],
range: ["#2980b9", "#e67e22"],
legend: true
},
x: { label: "Effect size (β)", grid: true },
y: { domain, label: null, tickSize: 0 },
marks: [
Plot.ruleX([0], { stroke: "#bbb", strokeWidth: 1.5 }),
Plot.ruleY(rows, {
x1: "beta_bmi", x2: "beta_no_bmi", y: "is_index",
stroke: d => d.beta_no_bmi - d.beta_bmi > 0 ? "#8e44ad" : "#27ae60",
strokeWidth: 3, strokeOpacity: 0.65
}),
Plot.dot(paired, {
x: "beta", y: "is_index", fill: "analysis",
r: d => d.pvalue < 0.05 ? 9 : 6, opacity: 0.9,
title: d => [
d.is_index,
d.analysis,
"β = " + d.beta.toFixed(5),
"p = " + d.pvalue.toExponential(3)
].join("\n")
}),
Plot.text(rows, {
x: d => (d.beta_bmi + d.beta_no_bmi) / 2,
y: "is_index",
text: d => "Δ=" + (d.beta_no_bmi - d.beta_bmi > 0 ? "+" : "") +
(d.beta_no_bmi - d.beta_bmi).toFixed(4),
dy: -12, fontSize: 8.5, fill: "#444", fontWeight: "600"
})
]
})
}How to read this chart: Each bar shows the median % of a variant’s genetic effect that is explained by BMI, computed across IS indices using the Baron–Kenny formula. Purple (positive %) = adjusting for BMI shrinks the effect; BMI mediates part of the association. Green (negative %) = the effect is stronger after BMI adjustment; the variant acts independently of BMI (or is suppressed by it). A value near 100% means virtually the entire genetic effect operates through BMI; near 0% means it is BMI-independent.
{
if (joinedFiltered.length === 0)
return html`<p style="color:#888;padding:1rem;">No data matches current filters.</p>`
// Baron-Kenny proportion mediated: PM = (β_total − β_direct) / |β_total|
// β_total = beta_no_bmi (unadjusted = total effect)
// β_direct = beta_bmi (BMI-adjusted = direct effect)
const all = d3.rollups(
joinedFiltered.filter(d => Math.abs(d.beta_no_bmi) >= 0.005),
v => {
const pms = v.map(d =>
Math.max(-300, Math.min(300,
(d.beta_no_bmi - d.beta_bmi) / Math.abs(d.beta_no_bmi) * 100
))
)
if (pms.length < 3) return null
return {
median_pm: d3.median(pms),
n_att: pms.filter(p => p > 0).length,
n_total: v.length
}
},
d => d.gene_snp_ra
)
.map(([gsr, s]) => s === null ? null : { gene_snp_ra: gsr, ...s })
.filter(d => d !== null && Math.abs(d.median_pm) < 200)
.sort((a, b) => b.median_pm - a.median_pm)
if (all.length === 0)
return html`<p style="color:#888;padding:1rem;">Insufficient data after filtering. Try relaxing filters.</p>`
const top10 = all.slice(0, 10)
const bottom10 = all.slice(-10)
const med = [...top10, ...bottom10]
.filter((d, i, arr) => arr.findIndex(x => x.gene_snp_ra === d.gene_snp_ra) === i)
.sort((a, b) => a.median_pm - b.median_pm)
const lm = Math.min(260, Math.max(150, d3.max(med, d => d.gene_snp_ra.length) * 6))
// Threshold: bars wider than 18% get white label inside; narrower get dark label outside
const INSIDE_THRESH = 18
return Plot.plot({
width,
height: Math.max(420, med.length * 26 + 130),
marginLeft: lm, marginRight: 90, marginBottom: 60,
style: { fontSize: "11px" },
color: {
domain: ["BMI attenuates", "BMI amplifies"],
range: ["#8e44ad", "#27ae60"],
legend: true
},
x: { label: "Median % of genetic effect mediated by BMI (Baron–Kenny: (β unadj − β adj) / |β unadj| × 100)", grid: true },
y: { label: null, tickSize: 0, domain: med.map(d => d.gene_snp_ra) },
marks: [
Plot.ruleX([0], { stroke: "#888", strokeWidth: 1.2 }),
Plot.ruleX([100], { stroke: "#bbb", strokeWidth: 1, strokeDasharray: "4,3" }),
Plot.barX(med, {
x: "median_pm", y: "gene_snp_ra",
fill: d => d.median_pm > 0 ? "BMI attenuates" : "BMI amplifies",
rx: 2,
title: d => [
d.gene_snp_ra,
"Median % mediated: " + d.median_pm.toFixed(1) + "%",
"BMI-attenuated in " + d.n_att + " of " + d.n_total + " IS indices"
].join("\n")
}),
// Labels INSIDE wide bars (white, bold)
Plot.text(med.filter(d => Math.abs(d.median_pm) >= INSIDE_THRESH), {
x: d => d.median_pm / 2,
y: "gene_snp_ra",
text: d => d.median_pm.toFixed(1) + "%",
textAnchor: "middle",
fontSize: 9, fontWeight: "bold", fill: "white"
}),
// Labels OUTSIDE narrow bars (dark, just past bar end)
Plot.text(med.filter(d => Math.abs(d.median_pm) < INSIDE_THRESH), {
x: d => d.median_pm,
y: "gene_snp_ra",
text: d => d.median_pm.toFixed(1) + "%",
dx: d => d.median_pm >= 0 ? 5 : -5,
textAnchor: d => d.median_pm >= 0 ? "start" : "end",
fontSize: 9, fill: "#333"
})
]
})
}geneRollup = d3.rollups(
filtered,
v => ({
min_pvalue: d3.min(v, d => +d.pvalue),
mean_beta: d3.mean(v, d => +d.beta),
n_sig: v.filter(d => +d.pvalue < 0.05).length,
n_variants: new Set(v.map(d => d.gene_snp_ra)).size
}),
d => d.nearest_gene,
d => d.is_index
).flatMap(([gene, indices]) =>
indices.map(([is_index, stats]) => ({ nearest_gene: gene, is_index, ...stats }))
)
uniqueGenes = [...new Set(geneRollup.map(d => d.nearest_gene))]
.sort((a, b) => {
const minA = Math.min(...geneRollup.filter(d => d.nearest_gene === a).map(d => d.min_pvalue))
const minB = Math.min(...geneRollup.filter(d => d.nearest_gene === b).map(d => d.min_pvalue))
return minA - minB
})
.slice(0, 80)
geneRollupFiltered = geneRollup.filter(d => uniqueGenes.includes(d.nearest_gene))
geneH = Math.max(400, uniqueGenes.length * 16 + 120)
geneW = Math.max(width, visibleIndices.length * cellW + 280)
geneLM = uniqueGenes.length > 0
? Math.min(200, Math.max(80, Math.max(...uniqueGenes.map(s => s.length)) * 7))
: 100Plot.plot({
width: geneW, height: geneH,
marginLeft: geneLM, marginBottom: 110, marginRight: 80,
style: { background: "#fafafa", fontFamily: "system-ui, sans-serif", fontSize: "11px" },
color: { type: "diverging", scheme: "RdBu", pivot: 0, domain: [-0.02, 0.02],
legend: true, label: "Mean β", reverse: true },
x: { domain: visibleIndices, tickRotate: -55, label: "Insulin Sensitivity Index", labelAnchor: "right" },
y: { domain: uniqueGenes, label: "Gene (top 80 by min p-value)", tickSize: 0 },
marks: [
Plot.cell(geneRollupFiltered, {
x: "is_index", y: "nearest_gene", fill: d => d.mean_beta,
title: d => [
"Gene: " + d.nearest_gene,
"IS Index: " + d.is_index,
"Mean β: " + d.mean_beta.toFixed(5),
"Min p: " + d.min_pvalue.toExponential(3),
"Sig. assoc: " + d.n_sig,
"Variants: " + d.n_variants
].join("\n"),
stroke: "#e0e0e0", strokeWidth: 0.4, rx: 1
}),
Plot.cell(geneRollupFiltered.filter(d => d.min_pvalue < 0.05), {
x: "is_index", y: "nearest_gene",
stroke: "#111", strokeWidth: 1.2, fill: "none", rx: 1
})
]
})geneSummary = d3.rollups(
filtered,
v => ({
n_variants: new Set(v.map(d => d.gene_snp_ra)).size,
n_sig_assoc: v.filter(d => +d.pvalue < 0.05).length,
best_pvalue: d3.min(v, d => +d.pvalue),
best_index: v.reduce((a, b) => +a.pvalue < +b.pvalue ? a : b).is_index,
max_abs_beta: d3.max(v, d => Math.abs(+d.beta))
}),
d => d.nearest_gene
).map(([gene, stats]) => ({ gene, ...stats }))
.sort((a, b) => a.best_pvalue - b.best_pvalue)
Inputs.table(geneSummary, {
columns: ["gene","n_variants","n_sig_assoc","best_pvalue","best_index","max_abs_beta"],
header: {
gene: "Gene", n_variants: "# Variants", n_sig_assoc: "Sig. Assoc. (p<0.05)",
best_pvalue: "Best P-value", best_index: "Best IS Index", max_abs_beta: "Max |β|"
},
format: {
best_pvalue: x => x.toExponential(3),
max_abs_beta: x => x.toFixed(5)
},
sort: "best_pvalue", reverse: false, rows: 25
})Volcano
Effect size (β) vs −log₁₀(p-value) for each variant. Use the dropdown to focus on a single IS index or view all 23 at once in a grid. Dashed lines mark p = 0.05 (orange) and p = 0.001 (red).
viewof volcanoIndex = Inputs.select(
["All Indices", ...visibleIndices],
{ label: "IS Index (All = 3-column grid)", value: "All Indices" }
){
const vData = filtered.map(d => ({
...d,
log10p: -Math.log10(+d.pvalue + 1e-300),
sig: +d.pvalue < 0.001 ? "p < 0.001" : +d.pvalue < 0.05 ? "p < 0.05" : "NS"
}))
const pal = { "p < 0.001": "#c0392b", "p < 0.05": "#e67e22", "NS": "#bdc3c7" }
if (volcanoIndex !== "All Indices") {
const sub = vData.filter(d => d.is_index === volcanoIndex)
return Plot.plot({
width, height: 500,
marginLeft: 60, marginBottom: 50, marginTop: 20, marginRight: 20,
style: { fontSize: "11px" },
color: { domain: Object.keys(pal), range: Object.values(pal), legend: true, label: "Significance" },
x: { label: "Effect size (β)", grid: true },
y: { label: "-log₁₀(p-value)", grid: true },
marks: [
Plot.dot(sub, {
x: d => +d.beta, y: "log10p", fill: "sig", r: 5, opacity: 0.8,
title: d => d.gene_snp_ra + "\nβ = " + (+d.beta).toFixed(5) + "\np = " + (+d.pvalue).toExponential(3)
}),
Plot.ruleX([0], { stroke: "#aaa", strokeWidth: 1.2 }),
Plot.ruleY([-Math.log10(0.05)], { stroke: "#e67e22", strokeDasharray: "6,3", strokeWidth: 1.5 }),
Plot.ruleY([-Math.log10(0.001)], { stroke: "#c0392b", strokeDasharray: "3,3", strokeWidth: 1.5 }),
Plot.text(sub.filter(d => +d.pvalue < 1e-4), {
x: d => +d.beta, y: "log10p", text: "gene_snp_ra", dy: -8, fontSize: 8, fill: "#333"
})
]
})
}
// All Indices: 3-column mini-plot grid
const nCols = 3
const sw = Math.max(220, Math.floor((width - 32) / nCols))
const grid = html`<div style="display:grid;grid-template-columns:repeat(${nCols},1fr);gap:6px;">`
for (const idx of visibleIndices) {
const sub = vData.filter(d => d.is_index === idx)
grid.appendChild(html`<div style="border:1px solid #dde3ec;border-radius:6px;padding:4px;background:#fafafa;">
<div style="font-size:9.5px;font-weight:700;color:#2c3e50;padding:2px 4px;text-align:center;">${idx}</div>
${Plot.plot({
width: sw - 10, height: 180,
marginLeft: 38, marginBottom: 26, marginTop: 4, marginRight: 6,
style: { fontSize: "8px" },
color: { domain: Object.keys(pal), range: Object.values(pal) },
x: { label: "β" },
y: { label: "-log₁₀p" },
marks: [
Plot.dot(sub, {
x: d => +d.beta, y: "log10p", fill: "sig", r: 2.5, opacity: 0.75,
title: d => d.gene_snp_ra + "\nβ=" + (+d.beta).toFixed(5) + "\np=" + (+d.pvalue).toExponential(3)
}),
Plot.ruleX([0], { stroke: "#ccc", strokeWidth: 1 }),
Plot.ruleY([-Math.log10(0.05)], { stroke: "#e67e22", strokeDasharray: "4,3", strokeWidth: 1 }),
Plot.ruleY([-Math.log10(0.001)], { stroke: "#c0392b", strokeDasharray: "2,2", strokeWidth: 1 })
]
})}
</div>`)
}
return grid
}📖 References
Suzuki K, Hatzikotoulas K, Southam L, Taylor HJ, Yin X, Lorenz KM, et al. Genetic drivers of heterogeneity in type 2 diabetes pathophysiology. Nature. 2024;627:347–357. doi:10.1038/s41586-024-07019-6
Suleman S, Ängquist L, Linneberg A, Hansen T, Grarup N. Exploring the genetic intersection between obesity-associated genetic variants and insulin sensitivity indices. Sci Rep. 2025;15(1):15761. doi:10.1038/s41598-025-98507-w · PMID: 40328835
👁 page views