< cd ~/raba.pl

Business products

EEG biofeedback demo

Make an abstract signal visible enough to explain, without requiring a headset or uploading a recording.

  • Prototype
  • April 2026
  • Builder; made for Sztuka Harmonii, which owns the code

The problem

The interface needed to connect the raw signal, electrode positions and frequency bands into one understandable view. Processing a local recording also had to work without sending the file to a server.

My part

Built for Sztuka Harmonii, which owns the code. Public recordings and local files power the demo.

What this shows

I can translate a specialized domain into an interactive explanation and build the data processing needed to support it.

Where it started

I built this browser demo for Sztuka Harmonii. It uses public PhysioNet recordings to illustrate changes in EEG activity, and can open a visitor's own EDF files locally.

See it in action

Product walkthrough · 1:30 · 60 FPS · English narration
EEG biofeedback demo interface

English AI narration · Subtitles included · Play with sound, or read the transcript.

Read the video transcript

0:00 I built this interactive brain-signal demo for Sztuka Harmonii, using a public research recording.

0:08 The scalp map turns nineteen electrode signals into an animated view of band power.

0:15 Changing the frequency band updates the map and the values together.

0:22 Different montage presets show what changes when fewer electrodes are available.

0:35 The signal view keeps the original channels visible alongside the visual summary.

0:41 A shared timeline makes changes across recordings easier to compare.

0:50 In these recordings, the share of alpha activity is higher with eyes closed than with eyes open.

1:00 People can load their own recording. File processing stays inside the browser.

1:07 The preprocessing settings are documented, so the visualisation can be traced back to the signal pipeline.

1:23 It is a focused demonstration of making technical information explorable and understandable.

The decisions behind the product

Connect the different views of the signal

I built a scalp map, band-share display, 19-channel signal preview and timeline. Moving through a recording keeps those views focused on the same moment.

Keep file processing in the browser

A Web Worker parses EDF files and computes band power. Local files stay on the device, with storage in IndexedDB and a browser-generated PDF report.

Give the demo a reproducible foundation

Bundled public recordings are preprocessed with MNE-Python. The interface supports Polish and English and can run from static data without the optional server.

What came out of the work

A visual explanation people can explore

The demo connects 19 electrode positions with signals, frequency bands and an interactive timeline, using two public eyes-open and eyes-closed recordings.

Local analysis by design

Supported EDF files can be opened and processed without uploading them. The product replays recordings; it is not a live headset integration or evidence of a clinical result.

  • 19recorded EEG channels visualized togetherRecording demo · checked 6 Oct 2026
  • LocalEDF files processed without uploading themRecording demo · checked 6 Oct 2026

Inside the implementation

Explore the features, architecture and quality checks

What I built

  • React 18 and Vite 6 single-page app in Polish and English that runs on static, precomputed JSON
  • Scalp map: a Three.js shader interpolates band power between 19 electrode positions by inverse distance weighting, 4 frames a second
  • Five bands from delta (up to 4 Hz) to gamma (30 to 45 Hz), shown as shares of total power, with the dominant band as a mental-state readout
  • Signal preview of all 19 channels in a scrolling 4 s window, downsampled to 80 Hz and drawn on a 2D canvas
  • Recording comparison of band power over time, and a session timeline coloured by the dominant band that seeks on click
  • Montage presets replay the same session through 4 electrodes (Fz, Cz, Pz, O1) or 2 (Cz, Fz)
  • Local EDF files parsed in a Web Worker that runs its own FIR filter and Welch band power in TypeScript; files are kept in IndexedDB and channels it cannot place are listed as skipped
  • PDF session report generated in the browser with @react-pdf/renderer
  • Python precompute with MNE-Python: the 19 standard 10-20 channels, 1 to 45 Hz band-pass, 50 Hz notch, Welch band power over 2 s windows every 0.25 s

How it works

  1. RecordPhysioNet EEG Motor Movement/Imagery dataset, subject 1: a minute with eyes open (run 1) and a minute with eyes closed (run 2).
  2. CleanMNE-Python keeps the 19 standard 10-20 channels, band-passes 1 to 45 Hz and notches out 50 Hz.
  3. Window2 s windows every 0.25 s give 237 frames per recording.
  4. BandsWelch spectra are integrated into five bands per channel; the channel mean of each band becomes a share of the total.
  5. ExportFrames, an 80 Hz signal preview and a manifest are written as static JSON.
  6. ReplayThe browser plays 4 frames a second: scalp map, band shares, dominant state, signal and timeline.

Quality and reliability

  • Real public data: the PhysioNet EEG Motor Movement/Imagery dataset (Schalk et al., 2004; Goldberger et al., 2000), with electrode positions from NeuroAnalyzer.jl
  • Opened EDF files stay on the device: the app's only network calls are GET requests for the bundled data, the electrode layout and a health check
  • Server mode is optional: when /api/health does not answer within 2 s, the FastAPI option is shown as unavailable and the app stays on static JSON
  • EDF files longer than 5 minutes are refused with a message instead of being cut silently
  • Known limit: the demo replays recordings and local EDF files; it does not connect to a headset
  • Known limit: one subject and two one-minute runs, so the numbers illustrate the method, not a clinical result

Technology

  • React 18
  • TypeScript
  • Vite 6
  • Tailwind CSS 3
  • Three.js
  • GLSL
  • Framer Motion
  • fft.js
  • @react-pdf/renderer
  • Web Workers
  • IndexedDB
  • Python
  • MNE-Python
  • NumPy
  • FastAPI
  • Vercel

Explore another problem I worked on

>_ Your next project

Liked what you saw?
Let’s get in touch!

Have an idea, a challenge, or a role in mind? I’d love to hear about it.

Let’s talk

>_ Start a conversation

Liked what you saw?
Let’s get in touch!

Tell me what you’re working on. Let’s see how I can help.

Email mepatryk@raba.pl
Send a message