RF-Behavior-gallery / index.html
Si-Z's picture
Update the gallery
5fec5e7 verified
Raw History Blame Contribute Delete
7.65 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RF-Behavior gallery</title>
<meta name="description" content="Figures of the RF-Behavior dataset, made by its reader scripts: radar, LoRa, RFID, motion capture, IMU.">
<style>
:root {
--bg: #ffffff; --panel: #f6f7f9; --ink: #1f2328; --muted: #6b7280; --line: #e5e7eb;
--accent: #2b6cb0; --accent-ink: #ffffff;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg: #0f1216; --panel: #181c22; --ink: #e6e8eb; --muted: #9aa3ad; --line: #2a3038;
--accent: #6ea8e5; --accent-ink: #0f1216;
}
}
:root[data-theme="dark"] {
--bg: #0f1216; --panel: #181c22; --ink: #e6e8eb; --muted: #9aa3ad; --line: #2a3038;
--accent: #6ea8e5; --accent-ink: #0f1216;
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--ink);
font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
main { max-width: 1400px; margin: 0 auto; padding: 24px 16px 48px; }
h1 { font-size: 26px; margin: 0 0 6px; }
p.lead { margin: 0 0 18px; color: var(--muted); max-width: 900px; }
a { color: var(--accent); }
.controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px;
background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 14px; }
label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); }
select { font: inherit; color: var(--ink); background: var(--bg); border: 1px solid var(--line);
border-radius: 6px; padding: 7px 8px; }
figure { margin: 18px 0 0; }
figure img { display: block; max-width: 100%; height: auto; border: 1px solid var(--line);
border-radius: 8px; background: #ffffff; }
figcaption { color: var(--muted); font-size: 13px; margin-top: 6px; }
table { border-collapse: collapse; margin-top: 16px; font-size: 14px; max-width: 900px; }
td { border-bottom: 1px solid var(--line); padding: 6px 12px 6px 0; vertical-align: top; }
td:first-child { color: var(--muted); white-space: nowrap; width: 150px; }
.note { color: var(--muted); font-size: 13px; margin-top: 24px; }
.missing { color: var(--muted); padding: 24px; border: 1px dashed var(--line); border-radius: 8px; }
</style>
</head>
<body>
<main>
<h1>RF-Behavior gallery</h1>
<p class="lead">Figures of the <a href="https://huggingface.co/datasets/Si-Z/RF-Behavior">RF-Behavior
dataset</a>, drawn by its own reader scripts. 61 participants, 21 gestures, 10 activities, 6 affective
behaviors; 13 mmWave radars, LoRa, RFID, infrared motion capture, IMUs; a laboratory, a living room, and an
industrial site. This gallery shows one participant per campaign and environment, every class, repetition 01.
Paper: <a href="https://arxiv.org/abs/2511.06020">arXiv:2511.06020</a>.</p>
<div class="controls">
<label>Environment <select id="env"></select></label>
<label>Campaign <select id="campaign"></select></label>
<label>Participant <select id="user"></select></label>
<label>Class <select id="cls"></select></label>
<label>Modality <select id="modality"></select></label>
<label>View <select id="view"></select></label>
<label id="radars-label">Radars <select id="radars"></select></label>
</div>
<figure>
<img id="figure" alt="">
<figcaption id="caption"></figcaption>
</figure>
<table id="facts"></table>
<p class="note">The figures come from <code>scripts/&lt;Modality&gt;/read_vis.py</code> of the dataset
(MIT license). Data: CC BY-NC-SA 4.0, academic research only. The interactive explorer (any trial, any
window) is the Gradio app in the dataset's companion repository.</p>
</main>
<script>
// Gallery: dropdowns over figures/manifest.json (made by build_gallery.py with the dataset's readers).
(async function () {
const M = await (await fetch("manifest.json")).json();
const $ = id => document.getElementById(id);
const sel = { env: $("env"), campaign: $("campaign"), user: $("user"), cls: $("cls"), modality: $("modality"),
view: $("view"), radars: $("radars") };
const RADAR_LABEL = { all: "all radars", ground: "ground radars (5-12)" };
const CAMPAIGN_LABEL = {};
M.trials.forEach(t => { CAMPAIGN_LABEL[t.campaign] = `${t.campaign} ${t.campaign_name}`; });
function fill(select, options, keep) {
const old = select.value;
select.innerHTML = "";
options.forEach(([label, value]) => {
const o = document.createElement("option"); o.textContent = label; o.value = value; select.append(o);
});
if (keep && options.some(([, v]) => v === old)) select.value = old;
}
const uniq = xs => [...new Set(xs)];
const inEnv = () => M.trials.filter(t => String(t.environment_id) === sel.env.value);
const trialsOf = () => inEnv().filter(t => t.campaign === sel.campaign.value);
const trial = () => inEnv().find(t => t.campaign === sel.campaign.value && t.user === sel.user.value
&& t.cls === sel.cls.value);
function onEnv() {
const cs = uniq(inEnv().map(t => t.campaign));
fill(sel.campaign, cs.map(c => [CAMPAIGN_LABEL[c], c]), true);
onCampaign();
}
function onCampaign() { fill(sel.user, uniq(trialsOf().map(t => t.user)).map(u => [u, u]), true); onUser(); }
function onUser() {
const ts = trialsOf().filter(t => t.user === sel.user.value);
fill(sel.cls, ts.map(t => [`${t.cls} ${t.class_name}`, t.cls]), true);
onClass();
}
function onClass() { fill(sel.modality, trial().modalities.map(m => [M.modality_label[m], m]), true); onModality(); }
function onModality() {
fill(sel.view, M.views[sel.modality.value].map(v => [v, v]), true);
const radar = sel.modality.value === "radar";
$("radars-label").style.display = radar ? "" : "none";
if (radar) fill(sel.radars, ["all", "ground"].map(r => [RADAR_LABEL[r], r]), true);
show();
}
function show() {
const t = trial();
const radars = sel.modality.value === "radar" ? sel.radars.value : "-";
const f = M.figures.find(g => g.environment_id === t.environment_id && g.campaign === t.campaign && g.user === t.user && g.cls === t.cls
&& g.modality === sel.modality.value && g.view === sel.view.value
&& g.radars === radars);
const img = $("figure");
if (!f) { img.removeAttribute("src"); $("caption").textContent = "No figure for this choice."; return; }
img.src = f.file;
img.alt = `${M.modality_label[f.modality]}, ${f.view}`;
const win = f.window[0] === null && f.window[1] === null ? "whole trial"
: `${f.window[0] ?? 0} to ${f.window[1] ?? "end"} s`;
$("caption").textContent = `${t.environment} ${t.campaign} / ${t.user} / ${t.cls} ${t.class_name}, ` +
`repetition ${t.rep} - ${M.modality_label[f.modality]}, ${f.view.split(":")[0]} view, ${win}` +
(f.modality === "radar" ? `, ${RADAR_LABEL[f.radars]}` : "");
$("facts").innerHTML = t.facts.map(([k, v]) => `<tr><td>${k}</td><td>${v}</td></tr>`).join("");
}
const envs = [];
M.trials.forEach(t => { if (!envs.some(e => e[1] === String(t.environment_id))) envs.push([t.environment, String(t.environment_id)]); });
fill(sel.env, envs);
sel.env.onchange = onEnv; sel.campaign.onchange = onCampaign; sel.user.onchange = onUser; sel.cls.onchange = onClass;
sel.modality.onchange = onModality; sel.view.onchange = show; sel.radars.onchange = show;
onEnv();
})();
</script>
</body>
</html>