-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtutorial.html
More file actions
316 lines (300 loc) · 18.4 KB
/
Copy pathtutorial.html
File metadata and controls
316 lines (300 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tutorial · DIMS-network</title>
<meta name="description" content="Two ways to build your own DIMS dashboard for your data: the no-code Dashboard Builder, or creating a study with dims-case and editing it by hand." />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<nav class="nav">
<div class="wrap nav-in">
<a class="brand" href="index.html">DIMS-network</a>
<div class="nav-links">
<a href="index.html">Home</a>
<a href="tutorial.html" class="active">Tutorial</a>
<a href="docs/index.html">Docs</a>
<a href="https://github.com/dims-network">GitHub ↗</a>
</div>
</div>
</nav>
<div class="wrap">
<header>
<div class="eyebrow">Tutorial</div>
<h1>Build your own DIMS dashboard</h1>
<div class="callout"><b>What your data needs to look like</b> :
<ul>
<li><b>Group files by session.</b> Everything from one recording shares a single
<b>session ID</b> — the video, its time series, and its transcript.</li>
<li><b>Video</b> — an <code>.mp4</code>.</li>
<li><b>Time series</b> — a <code>.csv</code> with a time column (named
<code>Time</code>, <code>time</code>, any casing) in <b>seconds</b>, plus one or more
measurement columns. The <b>builder auto-splits</b> a
multi-column CSV into one data type per column; if you hand-edit the study, use
<b>one</b> measurement column per file.</li>
<li><b>Transcript</b> (optional) — JSON shaped as
<code>{ "segments": [ {start, end, speaker, text} ] }</code>.</li>
<li><b>ELAN</b> (optional) — an <code>.eaf</code> file.</li>
</ul>
<b>Most important:</b> the <code>Time</code> axis is mapped directly onto the video clock, so a
session's <b>video length and time-series length should match</b>. If they differ, the video and
signals won't line up (dead space, or the signal cut off).</div>
<div class="toggle-group" role="tablist" aria-label="Choose your path">
<button class="toggle-btn active" data-panel="builder" role="tab" aria-selected="true">
🧩 No-code <span class="tag">Dashboard Builder</span></button>
<button class="toggle-btn" data-panel="manual" role="tab" aria-selected="false">
⌨️ Hands-on <span class="tag">edit the study</span></button>
</div>
</header>
<!-- PATH 1 — non-technical -->
<section id="builder" class="tabpanel">
<div class="path builder">
<h3>For non-coders — the Dashboard Builder</h3>
<div class="callout"><b>Install:</b> DIMS is <b>not on PyPI yet</b>, so install it from a
checkout of <a href="https://github.com/dims-network/dims">dims-network/dims</a>:
<pre class="code">git clone https://github.com/dims-network/dims
pip install -e "./dims[builder]"
dims-builder</pre>
The last command opens the wizard in your browser and walks you through it.
<span class="muted">Once the package is published this becomes
<code>pip install "dims-network[builder]"</code>.</span></div>
<p class="sub">A point-and-click app: drop your files in, click through a wizard, get a
ready-to-deploy dashboard. No JSON editing, no file renaming, no terminal scripts.</p>
<div class="callout"><b>One prerequisite:</b> you need <b>Python 3.10–3.12</b> installed (a free,
one-time install from <a href="https://www.python.org/downloads/">python.org/downloads</a>).
3.13 works for everything except motion capture, which has no <code>mediapipe</code> wheel for it.
Once the builder is installed, <b>no internet is required</b> to build a dashboard.</div>
<ol class="steps">
<li>
<h4>Get the builder</h4>
<p><a class="dl" href="https://github.com/dims-network/dims">dims-network/dims →</a></p>
<p>Clone it, or download the ZIP from that page and unzip it. The builder is the
<code>apps/builder/</code> folder, and the dashboard code it builds against is in the
same repository — so there is nothing else to fetch.</p>
</li>
<li>
<h4>Start it — one click</h4>
<p>Double-click the launcher in <code>apps/builder/</code>. It installs everything the
first time and then opens the wizard in your browser:</p>
<ul>
<li><b>macOS:</b> <code>run.command</code></li>
<li><b>Windows:</b> <code>run.bat</code></li>
<li><b>Linux:</b> <code>run.sh</code></li>
</ul>
<div class="callout warn"><b>macOS — first time only:</b> you may see
<i>“Apple could not verify ‘run.command’ is free of malware.”</i> Click <b>Done</b>
(not <i>Move to Trash</i>), then open <b>System Settings → Privacy & Security</b>,
scroll to <b>Security</b>, and click <b>Open Anyway</b> next to <code>run.command</code>.
This only happens once. (It's macOS flagging any downloaded, unsigned script — not a
problem with the builder.)</div>
<p>Prefer the terminal? That also avoids the macOS prompt above — open a terminal in
<code>apps/builder/</code> and run exactly what the launcher runs:</p>
<pre class="code">pip install -r requirements.txt
python -m dims_builder</pre>
<p class="sub"><code>requirements.txt</code> installs what the builder needs, not the
builder itself, so run it as a module from that folder. If you installed the package
(<code>pip install -e "./dims[builder]"</code>) the command is just
<code>dims-builder</code>, from anywhere.</p>
</li>
<li>
<h4>Create a project</h4>
<p>Choose an empty output folder and a title/authors, and say <b>who may see the
data</b> — private is the default, and it turns on the commit hook, push hook and CI
check that keep recordings out of git. There is nothing to choose about the dashboard
code: one scaffold ships in the repository and it is the one used, so a study the
builder makes is identical to one made by hand.</p>
</li>
<li>
<h4>Add your files</h4>
<p>Drag in your <code>.mp4</code> video, your time-series <code>.csv</code> files, your
<code>_transcript.json</code>, and optionally an ELAN <code>.eaf</code>. The builder
recognises each file, groups them under a <b>session</b>, and checks them as you go —
so problems surface before you build.</p>
<p><b>Got one CSV with several signals?</b> Drop it in as-is — a CSV with a
<code>Time</code> column plus several measurement columns is <b>split automatically</b>
into one data type per column, so you don't have to prepare separate files by hand.</p>
</li>
<li>
<h4>Align video & data</h4>
<p>This is where the mismatch warned about at the top of this page gets fixed. Per
session, a shared-timeline preview shows the video track above each measurement track,
and you either <b>trim the video</b> to a window you pick with a dual-handle slider, or
<b>pad the measurements</b> with zeros at either end. Edits are
<b>non-destructive</b>: your originals are never modified, and the trim or pad is
applied only to the copies written at build time.</p>
</li>
<li>
<h4>Choose optional analyses</h4>
<p>Toggle <b>RQA</b>, <b>cross-wavelet</b>, <b>cross-RQA</b>, the <b>cross-effector
network</b>, and <b>ELAN</b> annotations — the wizard explains what each tab shows.</p>
<ul>
<li><b>RQA</b> — recurrence within a single signal; pick which data types to compute.</li>
<li><b>Cross-wavelet</b> & <b>cross-RQA</b> — coupling between <b>two</b> signals.
Pick the exact <b>pairs</b> to compute: chips show every possible pair (all selected by
default), and you click to toggle — so you can run, say,
<code>bodysync × neuralsync</code> and <code>neuralsync × gaze</code>
but skip <code>bodysync × gaze</code>. A signal can appear in several pairs.</li>
<li><b>Cross-effector network</b> — one picture of which signals are coupled with which,
moving with the playhead. It reads the cross-wavelet results, so it needs that
analysis and its chance level; group your measures here (two people, two conditions)
or every one of them lands in a single undifferentiated column.</li>
</ul>
<p>Each analysis has a <b>Settings</b> panel for what the study can tune — the recurrence
window and target rate, the cross-wavelet picture size and its surrogate count. A line
at the foot of the step totals up how many runs that comes to and flags the slow ones,
because the first sign that a choice was expensive should not be being forty minutes
into the next step.</p>
</li>
<li>
<h4>Build & precompute</h4>
<p>Build writes <code>config.json</code> and copies your files into the exact
<code>assets/</code> layout. Precompute then runs the RQA / cross-wavelet / cross-RQA
steps for you in a project-local Python environment — progress streams live.</p>
<div class="callout warn"><b>The chance level is the expensive part.</b> Coherence is only
interpretable against a level estimated by simulation, and that simulation is most of
the compute. The cost follows <b>pairs × recordings × number of scales</b> — not minutes
of video, so a long recording is not necessarily a slow one. At the publication setting
of 300 surrogates a twelve-recording study can take a couple of hours. Start with the
default of 100 to see the shape of your data, and raise it when you are ready to
report.</div>
</li>
<li>
<h4>Preview & deploy</h4>
<p>Preview opens the finished dashboard locally. The output folder is self-contained and
ready to host — the builder shows copy-paste commands for GitHub Pages, Netlify, or Vercel.</p>
</li>
</ol>
<a class="cta" href="https://github.com/dims-network/dims/tree/main/apps/builder">Open the Dashboard Builder →</a>
</div>
</section>
<!-- PATH 2 — technical -->
<section id="manual" class="tabpanel" hidden>
<div class="path manual">
<h3>For coders — start from the scaffold & edit by hand</h3>
<p class="sub">Full control: copy the empty dashboard scaffold, drop files into <code>assets/</code>
with the right names, edit <code>config.json</code>, and (optionally) run the analyses.</p>
<div class="callout"><b>You'll need:</b> <b>git</b> and <b>Python 3.10–3.12</b>
(<a href="https://www.python.org/downloads/">python.org/downloads</a>). 3.13 works for
everything except motion capture, for which <code>mediapipe</code> ships no wheel yet.</div>
<ol class="steps">
<li>
<h4>Start from the scaffold</h4>
<p>All DIMS code lives in one repository. Install it, then let it write
you a study: <code>dims-case new</code> copies the scaffold <b>and</b> the
pinned dashboard code into <code>vendor/</code>, which is what makes the
page load at all.</p>
<pre class="code">git clone https://github.com/dims-network/dims
pip install -e ./dims
dims-case new my-dashboard --visibility public <span class="c"># -> ./case-my-dashboard</span>
cd case-my-dashboard</pre>
<div class="callout warn"><b>Do not copy the scaffold directory by hand.</b>
It contains no <code>vendor/</code>, so eight script tags 404 and you get a
blank page with no error worth reading. <code>dims-case new</code> is the
command that produces something that runs.</div>
<div class="callout"><b>Working with recordings of people?</b> Decide up
front whether the data can be published, and keep private data out of
git from the very first commit — removing it afterwards means rewriting
history, by which time it has usually been pushed. See
<a href="https://github.com/dims-network/dims/blob/main/docs/contracts/data-visibility.md">the
data-visibility contract</a>.</div>
</li>
<li>
<h4>Add your assets with the exact names</h4>
<p>File names are a strict convention — the dashboard finds your data by name. For a
session id (e.g. <code>session1</code>) and a data type (e.g. <code>bodysync</code>):</p>
<div class="tree"><span class="p">assets/videos/</span>session1.mp4
<span class="p">assets/timeseries/</span>session1_bodysync.csv <span class="v"># Time + one measurement column</span>
<span class="p">assets/timeseries/</span>session1_neuralsync.csv
<span class="p">assets/transcripts/</span>session1_transcript.json <span class="v"># { "segments": [ {start,end,speaker,text} ] }</span>
<span class="p">assets/elan/</span>session1.eaf <span class="v"># optional (ELAN)</span></div>
<div class="callout warn"><b>Heads up:</b> the names must match exactly —
<code>{videoID}_{dataType}.csv</code>, <code>{videoID}.mp4</code>,
<code>{videoID}_transcript.json</code>. A missing <code>Time</code> column or a
mismatched name is the most common reason a tab stays blank.</div>
</li>
<li>
<h4>Edit <code>config.json</code></h4>
<p>Declare your sessions, their data types, which analyses to enable, and the page text:</p>
<pre class="code">{
<span class="k">"videoIDs"</span>: ["session1"],
<span class="k">"dataTypes"</span>: { "session1": ["bodysync", "neuralsync"] },
<span class="k">"include_RQA"</span>: ["bodysync", "neuralsync"],
<span class="k">"include_crosswavelet"</span>: [["bodysync", "neuralsync"]],
<span class="k">"include_cRQA"</span>: [["bodysync", "neuralsync"]],
<span class="k">"include_network"</span>: { "band": [0.0, 12.0] },
<span class="k">"include_elan"</span>: false,
<span class="k">"defaultWindowSize"</span>: 5,
<span class="k">"title"</span>: "My DIMS Dashboard",
<span class="k">"subtitle"</span>: "Dynamic Interaction and Multimodal Signals",
<span class="k">"authors"</span>: "Your name(s)",
<span class="k">"contacts"</span>: "you@example.org"
}</pre>
<p><code>include_RQA</code> is a list of data types. <b>Cross-wavelet</b> and
<b>cross-RQA</b> compare <b>pairs</b>: list each pair as <code>["typeA", "typeB"]</code>,
so you control exactly which pairs run. Every name you reference must have a matching CSV.
(<code>include_crosswavelet</code> also still accepts a flat list of data types, expanded
to all pairs, for backward compatibility.)</p>
<p><code>include_network</code> switches on the cross-effector network, drawn from the
cross-wavelet results — setting it also switches on the chance-level simulation, at 100
surrogates, because without one no edge can be told from chance. If your measures divide
into groups (two people, two instruments), say so here, or they all land in one column:
<code>"groups": [{"label": "Teacher", "match": "^teacher"}, …]</code>, each
<code>match</code> a regular expression on the data type name.</p>
</li>
<li>
<h4>(Optional) Precompute the analyses</h4>
<p>RQA, cross-wavelet, and cross-RQA read your CSVs and write JSON the dashboard loads. Run
them once whenever those toggles are on:</p>
<pre class="code"><span class="c"># already installed above; the analyses come with it</span>
python build_assets.py --check <span class="c"># what would run, and what is missing</span>
python build_assets.py</pre>
<p><code>--check</code> computes nothing. It reports which recordings it can
see, which analyses are switched on, and which time series it could not
find — the quickest way to discover that a file is misnamed.</p>
<p>This produces <code>assets/rqa/{videoID}_rqa_data.json</code>,
<code>assets/crosswavelet/{videoID}_crosswavelet_data.json</code>, and
<code>assets/crqa/{videoID}_crqa_data.json</code>. Each analysis runs
only if its key is set in <code>config.json</code>, so the one command
does the right thing whatever you enabled.</p>
</li>
<li>
<h4>Preview locally</h4>
<p>Use the bundled server (it supports HTTP Range requests, which the video needs for seeking):</p>
<pre class="code">python serve.py 8000 <span class="c"># then open http://localhost:8000</span></pre>
<p>It prints which study it is serving and from which directory — worth a
glance if you keep several dashboards side by side.</p>
</li>
<li>
<h4>Deploy</h4>
<p>A public study created with <code>dims-case</code> already carries the Pages workflow
that deploys it: push to <code>main</code> and it goes live. (Setting Pages up by hand
is branch <code>main</code>, folder <code>/ (root)</code>.) Any static host works —
just make sure it serves <b>Range requests</b>, or video seeking will not.</p>
</li>
</ol>
<a class="cta" href="https://github.com/dims-network/dims">Open the DIMS core →</a>
</div>
</section>
<footer>
DIMS-network · <a href="https://github.com/dims-network">github.com/dims-network</a>
</footer>
</div>
<script>
const btns = document.querySelectorAll(".toggle-btn");
const panels = document.querySelectorAll(".tabpanel");
function show(name){
panels.forEach(p => p.hidden = (p.id !== name));
btns.forEach(b => {
const on = b.dataset.panel === name;
b.classList.toggle("active", on);
b.setAttribute("aria-selected", on ? "true" : "false");
});
if (history.replaceState) history.replaceState(null, "", "#" + name);
}
btns.forEach(b => b.addEventListener("click", () => show(b.dataset.panel)));
// honor a deep link like tutorial.html#manual
if (location.hash === "#manual") show("manual");
</script>
</body>
</html>