Repository navigation
Expand file tree
/
Copy pathcontent.ts
More file actions
295 lines (285 loc) · 11.6 KB
/
Copy pathcontent.ts
File metadata and controls
295 lines (285 loc) · 11.6 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
// All text and links on the site live here. To add, change or remove a
// project, edit this file; the page renders whatever is in it.
export interface Link {
label: string;
href: string;
}
export interface Project {
name: string;
description: string;
/** Short labels shown under the description, e.g. platforms. */
tags?: string[];
/** The first link is shown as the primary button. */
links: Link[];
/** Path under /static, e.g. '/img/foo.webp'. */
image?: { src: string; alt: string };
icon?: string;
}
export interface Section {
id: string;
title: string;
intro?: string;
projects: Project[];
}
const gh = 'https://github.com/NexusDynamic';
const monorepo = `${gh}/liblsl.dart`;
const pkg = (name: string) => `${monorepo}/tree/main/packages/${name}`;
const app = (name: string) => `${monorepo}/tree/main/apps/${name}`;
const releases = (name: string) => `${monorepo}/releases?q=${name}&expanded=true`;
const docs = 'https://nexusdynamic.org/liblsl.dart';
const pub = (name: string) => `https://pub.dev/packages/${name}`;
export const site = {
title: 'NexusDynamic',
url: 'https://nexusdynamic.org',
tagline: 'Multimodal group social dynamics research, for everyone',
description:
'Open, cross-platform tools for group research: Lab Streaming Layer for Dart and Flutter, the LSL Viewer, multi-device timing tests, and the Rise Together game.',
intro:
'NexusDynamic builds a group-first, cross-platform suite of tools that make it easy to collect behavioural, EEG, motion capture or any other data. Anything with a Lab Streaming Layer integration, or any API that produces data, can be recorded or forwarded on as an LSL stream.',
github: gh,
pubPublisher: 'https://pub.dev/publishers/zeyus.com/packages',
lsl: 'https://labstreaminglayer.org/',
poster: '/FINAL-Coop_comp_paradigm-A0Poster_reduced.pdf',
citation: {
text: 'Ring, Zamm, Mathys & Kappel. liblsl.dart: A Dart native API for Lab Streaming Layer (LSL).',
href: 'https://doi.org/10.5281/zenodo.20340247'
}
};
export const nav: Link[] = [
{ label: 'Viewer', href: '#lsl-viewer' },
{ label: 'Game', href: '#rise-together' },
{ label: 'Packages', href: '#packages' },
{ label: 'Timing', href: '#timing' },
{ label: 'Research', href: '#research' },
{ label: 'Guides', href: `${docs}/guides.html` }
];
export const heroLinks: Link[] = [
{ label: 'Open LSL Viewer', href: `${docs}/lsl_viewer/` },
{ label: 'Play Rise Together', href: 'https://rt-lobby.nexusdynamic.org' },
{ label: 'Guides', href: `${docs}/guides.html` },
{ label: 'GitHub', href: gh }
];
/** Big cards at the top of the page. The id is the anchor used by the nav. */
export const featured: (Project & { id: string; eyebrow: string })[] = [
{
id: 'lsl-viewer',
eyebrow: 'App',
name: 'LSL Viewer',
description:
'An XDF file viewer and live LSL stream viewer. Open LabRecorder recordings of any size (in the browser they are read locally, never uploaded), view live streams with filters, re-referencing, power spectra and signal quality, record to XDF, replay recordings as LSL streams, and share streams across networks with the built-in WebSocket bridge and relay. It also works with OpenBCI Cyton and serial devices, including over WebSerial.',
tags: ['Web', 'Windows', 'macOS', 'Linux', 'Android'],
image: {
src: '/img/lsl-viewer.webp',
alt: 'LSL Viewer showing 35 channels of EEG from an XDF recording'
},
icon: '/nexusdynamic.svg',
links: [
{ label: 'Open the web app', href: `${docs}/lsl_viewer/` },
{ label: 'Downloads', href: releases('lsl_viewer') },
{ label: 'liblsl.dart website', href: `${docs}/` },
{ label: 'Bridge and relay guide', href: `${docs}/relay.html` },
{ label: 'Source', href: app('lsl_viewer') }
]
},
{
id: 'rise-together',
eyebrow: 'Game',
name: 'Rise Together',
description:
'A cooperative and competitive physics game. Keep the ball in the air by lifting the left and right sides of your paddle, climb through the levels and race the other team to the top. Play solo, team up in co-op, or play team against team online with quick match or a private room code. It includes a level editor and untimed play. It is the game version of our research paradigm, without the research logging and multimodal integration.',
tags: ['Web', 'Android', 'iOS', 'Windows', 'macOS', 'Linux'],
icon: '/img/rise-together-icon.webp',
links: [
{ label: 'Play online', href: 'https://rt-lobby.nexusdynamic.org' },
{ label: 'Play offline in the browser', href: 'https://nexusdynamic.org/RTGame/' },
{ label: 'Downloads', href: `${gh}/RTGame/releases` },
{ label: 'Source', href: `${gh}/RTGame` }
]
}
];
export const sections: Section[] = [
{
id: 'packages',
title: 'liblsl.dart',
intro:
'The core of the project: Lab Streaming Layer and XDF for Dart and Flutter, on Android, iOS, Linux, macOS, Windows and the web.',
projects: [
{
name: 'liblsl',
description:
'A Dart and Flutter interface to the C++ liblsl library, with full parity with the C API, for sending and receiving LSL streams in an application.',
links: [
{ label: 'pub.dev', href: pub('liblsl') },
{ label: 'Guide', href: `${docs}/streaming-between-devices.html` },
{ label: 'Source', href: pkg('liblsl') },
{ label: 'Cite (DOI)', href: site.citation.href }
]
},
{
name: 'xdf',
description:
'Read and write XDF files in pure Dart on every platform, including the web. Uses the same algorithms as pyxdf and is tested against it.',
links: [
{ label: 'pub.dev', href: pub('xdf') },
{ label: 'Source', href: pkg('xdf') }
]
},
{
name: 'signal_core',
description:
'A format-agnostic multichannel signal engine (summary pyramids, filters) that powers the viewer and the xdf package.',
links: [
{ label: 'pub.dev', href: pub('signal_core') },
{ label: 'Source', href: pkg('signal_core') }
]
},
{
name: 'signal_viewer',
description:
'The viewer behind LSL Viewer as a Flutter library, with source providers for LSL streams, XDF recordings and serial devices, for applications that display their own data.',
links: [
{ label: 'pub.dev', href: pub('signal_viewer') },
{ label: 'Source', href: pkg('signal_viewer') }
]
},
{
name: 'lsl_tools',
description:
'The lsl command line tool: list, record to XDF, share across networks, bridge, relay, replay and generate LSL streams.',
links: [
{ label: 'pub.dev', href: pub('lsl_tools') },
{ label: 'Source', href: pkg('lsl_tools') },
{ label: 'Downloads', href: releases('lsl_viewer') }
]
},
{
name: 'Coordinators',
description:
'Coordinate experiments across devices: coordinator election, membership, heartbeats and synchronised data streams over LSL, a WebSocket hub or peer-to-peer WebRTC.',
links: [
{ label: 'Guide', href: `${docs}/coordinated-experiment.html` },
{ label: 'peer_coordinator', href: pub('peer_coordinator') },
{ label: 'liblsl_coordinator', href: pub('liblsl_coordinator') },
{ label: 'webrtc_coordinator', href: pub('webrtc_coordinator') }
]
},
{
name: 'serial_transport',
description:
'Serial devices from Dart on desktop and in the browser (WebSerial). The OpenBCI Cyton driver is built on it.',
links: [
{ label: 'pub.dev', href: pub('serial_transport') },
{ label: 'openbci_cyton', href: pub('openbci_cyton') },
{ label: 'Source', href: pkg('serial_transport') }
]
}
]
},
{
id: 'timing',
title: 'Timing and latency',
intro:
'Validate latency and synchronisation in your own lab, on the devices you plan to use, before you collect any data.',
projects: [
{
name: 'transport_timing',
description:
'An app that measures one-way latency, jitter, loss and clock drift between devices over LSL, WebSocket and WebRTC, with the devices coordinated automatically.',
tags: ['Windows', 'macOS', 'Linux', 'Android'],
links: [
{ label: 'Guide', href: `${docs}/validating-timing.html` },
{ label: 'Downloads', href: releases('transport_timing') },
{ label: 'Source', href: app('transport_timing') }
]
},
{
name: 'transport_timing_analysis',
description:
'Collates and visualises the logs of a timing run from all devices: latency distributions, loss, clock offsets and drift for every pair of devices.',
tags: ['Web', 'Windows', 'macOS', 'Linux', 'Android'],
links: [
{ label: 'Open the web app', href: `${docs}/transport_timing_analysis/` },
{ label: 'Downloads', href: releases('transport_timing_analysis') },
{ label: 'Source', href: app('transport_timing_analysis') }
]
},
{
name: 'timing_core',
description:
'The record format and analysis behind both apps. The logs are XDF files, so they also open in other XDF tools.',
links: [
{ label: 'pub.dev', href: pub('timing_core') },
{ label: 'Source', href: pkg('timing_core') }
]
},
{
name: 'button_display_latency',
description:
'A Flutter app that measures the input-to-display pipeline for different button implementations, with frame-accurate timing and sync pulses for external measurement.',
links: [{ label: 'Source', href: `${gh}/button_display_latency` }]
},
{
name: 'bela-lsl-timing',
description:
'Validate end-to-end device latency with a Bela, photodiodes and force-sensitive resistors.',
links: [
{ label: 'Source', href: `${gh}/bela-lsl-timing` },
{ label: 'Bela', href: 'https://bela.io/' }
]
},
{
name: 'Bela-liblsl',
description: 'A pre-compiled liblsl build for the Bela (BeagleBone Black).',
links: [{ label: 'Source', href: `${gh}/Bela-liblsl` }]
}
]
},
{
id: 'flutter',
title: 'Flutter packages',
intro: 'General-purpose packages built along the way, useful in any Flutter app.',
projects: [
{
name: 'flutter_multicast_lock',
description:
'Acquire multicast locks on Android (and safely do nothing on other platforms), which LSL discovery needs.',
links: [
{ label: 'pub.dev', href: pub('flutter_multicast_lock') },
{ label: 'Source', href: `${gh}/flutter_multicast_lock` }
]
},
{
name: 'flutter_refresh_rate_control',
description:
"Ask Android and iOS devices to use their highest refresh rate (such as ProMotion) and try to disable Android's adaptive refresh rate.",
links: [
{ label: 'pub.dev', href: pub('flutter_refresh_rate_control') },
{ label: 'Source', href: `${gh}/flutter_refresh_rate_control` }
]
},
{
name: 'easy_shared_preferences',
description:
'A wrapper around shared_preferences that makes app settings easier to manage and modular.',
links: [
{ label: 'pub.dev', href: pub('easy_shared_preferences') },
{ label: 'Source', href: `${gh}/easy_shared_preferences` }
]
}
]
}
];
export const research = {
id: 'research',
title: 'Research paradigm',
subtitle: 'Simultaneous cooperation and competition in groups',
paragraphs: [
'RiseTogether is a video-game-style experimental paradigm for studying simultaneous cooperation and competition in groups. It supports different group sizes and is built on the liblsl.dart framework, which coordinates and configures the experiment automatically in different labs, on different devices and with different numbers of participants.',
'The research code and data will be released once data collection is complete. Until then, see the poster for an overview, or play the game version, Rise Together.'
],
links: [
{ label: 'View the poster (PDF)', href: site.poster },
{ label: 'Play Rise Together', href: '#rise-together' }
] satisfies Link[],
image: { src: '/poster-thumbnail.jpg', alt: 'Conference poster for the framework and paradigm' }
};