https://github.com/hci-lab-um/web-ssvep-stimuli-generators
CSS and WebGL were adopted to implement four cross-platform Steady State Visually Evoked Potential (SSVEP) stimuli-generator libraries, whose stimuli are produced via constant-period and square wave approximation techniques, for use in a Brain-Computer Interface (BCI) context. These libraries are configured to run as spellers, yet can easily be altered to cater for a wide range of use cases.
Science Score: 36.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
✓Committers with academic emails
3 of 4 committers (75.0%) from academic institutions -
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (9.3%) to scientific vocabulary
Keywords
Repository
CSS and WebGL were adopted to implement four cross-platform Steady State Visually Evoked Potential (SSVEP) stimuli-generator libraries, whose stimuli are produced via constant-period and square wave approximation techniques, for use in a Brain-Computer Interface (BCI) context. These libraries are configured to run as spellers, yet can easily be altered to cater for a wide range of use cases.
Basic Info
Statistics
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
- Releases: 2
Topics
Metadata Files
README.md
SSVEP Stimuli-Generator Libraries
CSS and WebGL were adopted to implement four cross-platform Steady State Visually Evoked Potential (SSVEP) stimuli-generator libraries, whose stimuli are produced via constant-period and square wave approximation techniques, for use in a Brain-Computer Interface (BCI) context. These libraries are configured to run as spellers, yet can easily be altered to cater for a wide range of use cases.
More information about these libraries can be found in this peer reviewed publication by the same authors: Towards Accurate Browser-based SSVEP Stimuli Generation.
In alignment with existing documentation, it was found that CSS animations are more stable and performant than their WebGL counterparts.
Generating on-page stimuli
There are 4 stimuli generators in this repository, CSS+Square Wave Approximation, CSS+Constant Period, WebGL+Square Wave Approximation and WebGL+Constant Period.
After importing the library, you can create any number of stimuli on the page using the following data-* attributes:
data-frequency: specifying the SSVEP stimulus frequencydata-light-color: specifying the light color of the flickering SSVEP stimulusdata-dark-color: specifying the dark color of the flickering SSVEP stimulusdata-phase-shift: specifying the phase shift (frames delay) for the SSVEP stimulusdata-pattern: specifying the flickering button's pattern. You can choose fromsolid,dot,chequeredorlinepattern types.
The data-light-color and data-dark-color attributes define how colors are applied based on the chosen flickering pattern:
- Solid: The stimulus alternates between
data-light-coloranddata-dark-colorto create a flickering effect. - Chequered: The squares within the pattern will be displayed in
data-light-coloranddata-dark-color. - Dot: The dots will be displayed in
data-light-coloranddata-dark-color, while the background remains white. - Line: The background will be
data-dark-color, and the lines will bedata-light-color.
The following is a sample screenshot showcasing all four data-pattern types in action:

Begin Stimuli Generation
To begin stimuli generation, you must select your HTML elements and add to the manager
1. CSS
Stimuli can be defined as follows for CSS:
html
<button data-frequency="6.67" data-dark-color="0,0,0,1" data-light-color="255,255,255,1" data-phase-shift="0" data-pattern="solid">Button 1</button>
<button data-frequency="7" data-dark-color="0,255,0,1" data-light-color="0,0,255,1" data-phase-shift="0" data-pattern="chequered">Button 2</button>
<button data-frequency="8.57" data-dark-color="255,0,0,1" data-light-color="0,0,255,1" data-phase-shift="0" data-pattern="dot">Button 3</button>
<button data-frequency="10" data-dark-color="127,127,127,1" data-light-color="255,255,255,1" data-phase-shift="0" data-pattern="line">Button 4</button>
```html
import * as stimuli from "./dist/index.js"
const elements = document.querySelectorAll('button')
// ----------- CSS Methods ----------- const manager = new window.stimuli.CSS('approximation', elements.length) // const manager = new window.stimuli.CSS('periodic', elements.length)
elements.forEach(el => manager.set(el)) // Add Elements manager.start() // Start Stimuli Generation
```
2. WebGL
Stimuli can be defined as follows for WebGL:
html
<canvas id="canvas"></canvas>
<button data-frequency="6.67" data-dark-color="0,0,0,1" data-light-color="255,255,255,1" data-phase-shift="0" data-pattern="solid">
<span class="button-text">Button 1</span>
</button>
<button data-frequency="7" data-dark-color="0,255,0,1" data-light-color="0,0,255,1" data-phase-shift="0" data-pattern="chequered">
<span class="button-text">Button 2</span>
</button>
<button data-frequency="8.57" data-dark-color="255,0,0,1" data-light-color="0,0,255,1" data-phase-shift="0" data-pattern="dot">
<span class="button-text">Button 3</span>
</button>
<button data-frequency="10" data-dark-color="127,127,127,1" data-light-color="255,255,255,1" data-phase-shift="0" data-pattern="line">
<span class="button-text">Button 4</span>
</button>
```html
import * as stimuli from "./dist/index.js"
const elements = document.querySelectorAll('button')
// ----------- WebGL Methods ----------- const canvas = document.body.querySelector('canvas') const manager = new window.stimuli.WebGL('approximation', canvas, elements.length) // const manager = new window.stimuli.WebGL('periodic', canvas, elements.length)
elements.forEach(el => manager.set(el)) // Add Elements manager.start() // Start Stimuli Generation
```
```css
/* Styling the canvas so that it fills the whole screen and the button text above the canvas /
.button-text {
position: relative;
z-index: 2; / Contains a higher z-index than the canvas */
}
canvas {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1; /* Contains a lower z-index than the canvas */
} ```
Add Stimuli
You can add more stimuli by passing one or more elements to the start() method:
javascript
manager.start(document.getElementById('new_element'))
// manager.start(document.body.querySelectorAll('.other'))
This technique also allows you to selectively start a subset of elements.
Cancel Stimuli Generation
You can cancel all ongoing stimuli generation by calling the stop() method:
javascript
manager.stop()
Or stop a subset by passing one or more elements as the first argument:
javascript
manager.stop(document.getElementById('new_element'))
// manager.stop(document.body.querySelectorAll('.other'))
Node.js Example (Using CSS)
To use the SSVEP stimuli library in a Node.js project:
1. Install via npm. Run the following command: npm install ssvep-stimuli.
2. Use the following code in your JavaScript file:
```javascript const stimuli = require('./dist/index.js');
// Simulating HTML button elements for the example const elements = [ { frequency: 6.67, lightColor: '255,255,255,1', darkColor: '0,0,0,1', phaseShift: 0, pattern: 'solid' }, { frequency: 7, lightColor: '0,0,255,1', darkColor: '0,255,0,1', phaseShift: 0, pattern: 'chequered' }, { frequency: 8.57, lightColor: '0,0,255,1', darkColor: '255,0,0,1', phaseShift: 0, pattern: 'dot' }, { frequency: 10, lightColor: '255,255,255,1', darkColor: '127,127,127,1', phaseShift: 0, pattern: 'line' } ];
const manager = new stimuli.CSS('approximation', elements.length); // const manager = new stimuli.CSS('periodic', elements.length);
elements.forEach(el => manager.set(el)); manager.start(); ```
Node.js Example (Using WebGL)
To use the SSVEP stimuli library in a Node.js project:
1. Install via npm. Run the following command: npm install ssvep-stimuli.
2. Use the following code in your JavaScript file:
```javascript const stimuli = require('./dist/index.js');
// For WebGL, you would typically need to initialise a WebGL context.
// Here, we assume you're using a package like headless-gl or similar.
const { createCanvas } = require('canvas'); // Example: 'canvas' package for WebGL context in Node.js const canvas = createCanvas(800, 600); // Create a canvas to simulate the WebGL context
// Simulating HTML button elements for the example const elements = [ { frequency: 6.67, lightColor: '255,255,255,1', darkColor: '0,0,0,1', phaseShift: 0, pattern: 'solid' }, { frequency: 7, lightColor: '0,0,255,1', darkColor: '0,255,0,1', phaseShift: 0, pattern: 'chequered' }, { frequency: 8.57, lightColor: '0,0,255,1', darkColor: '255,0,0,1', phaseShift: 0, pattern: 'dot' } { frequency: 10, lightColor: '255,255,255,1', darkColor: '127,127,127,1', phaseShift: 0, pattern: 'line' } ];
const manager = new stimuli.WebGL('approximation', canvas, elements.length); // const manager = new stimuli.WebGL('periodic', canvas, elements.length);
elements.forEach(el => { manager.set(el); }); manager.start(); ```
Roadmap
- Add and remove elements based on visibility in the window.
- Dynamically change the frequency values applied to an element
- Automatically assign for maximum discriminability.
- Position WebGL Canvas behind arbitrary elements across an entire a webpage with scrolling.
- Expose a way to assign your own CSS rules and/or WebGL intensities
Known Issues
WebGL
- Dynamically adding elements using WebGL techniques will create too many contexts and halt execution.
Acknowledgments
These libraries were developed by Alison Camilleri to fulfill part of the requirements for the award of a Master of Science in Computer Information Systems degree.
Supervisory Team
Dr Chris Porter
Department of Computer Information Systems, Faculty of ICT
Dr Tracey Camilleri
Department of Systems & Control Engineering, Faculty of Engineering
Other Contributors
Garrett Flynn
Founding Partner at Brains@Play - Refactored the libraries for publication (April 2022)
Daniel Calleja & (https://github.com/dcalleja17)
Research Support Officer on the BrainWeb Project
- Arranged the functionality of data-dark-color (December 2024)
- Implemented different pattern types for stimuli for both CSS and WebGL (January 2025)
Owner
- Name: hci-lab-um
- Login: hci-lab-um
- Kind: organization
- Repositories: 6
- Profile: https://github.com/hci-lab-um
GitHub Events
Total
- Release event: 1
- Watch event: 1
- Delete event: 1
- Push event: 46
- Create event: 2
Last Year
- Release event: 1
- Watch event: 1
- Delete event: 1
- Push event: 46
- Create event: 2
Committers
Last synced: 4 months ago
Top Committers
| Name | Commits | |
|---|---|---|
| daniel-calleja17 | d****a@u****t | 34 |
| Garrett | g****n@u****u | 27 |
| Chris Porter | c****r@u****t | 16 |
| chrisporter-um | 4****m@u****m | 9 |
Issues and Pull Requests
Last synced: 7 months ago
All Time
- Total issues: 0
- Total pull requests: 1
- Average time to close issues: N/A
- Average time to close pull requests: less than a minute
- Total issue authors: 0
- Total pull request authors: 1
- Average comments per issue: 0
- Average comments per pull request: 0.0
- Merged pull requests: 1
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 0
- Pull requests: 1
- Average time to close issues: N/A
- Average time to close pull requests: less than a minute
- Issue authors: 0
- Pull request authors: 1
- Average comments per issue: 0
- Average comments per pull request: 0.0
- Merged pull requests: 1
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
Pull Request Authors
- daniel-calleja17 (1)
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 1
-
Total downloads:
- npm 78 last-month
- Total dependent packages: 1
- Total dependent repositories: 0
- Total versions: 10
- Total maintainers: 3
npmjs.org: ssvep-stimuli
A library for generating SSVEP stimuli on the browser
- Homepage: https://github.com/hci-lab-um/web-ssvep-stimuli-generators#readme
- License: GPL-3.0-or-later
-
Latest release: 0.1.7
published 10 months ago
Rankings
Maintainers (3)
Dependencies
- @babel/core ^7.17.2 development
- @babel/plugin-proposal-class-properties ^7.16.7 development
- @babel/plugin-transform-runtime ^7.17.0 development
- @babel/preset-env ^7.16.11 development
- @rollup/plugin-babel ^5.3.0 development
- @rollup/plugin-commonjs ^21.0.1 development
- @rollup/plugin-node-resolve ^13.1.3 development
- @web/rollup-plugin-copy ^0.3.0 development
- rollup ^2.67.1 development
- rollup-plugin-import-css ^3.0.2 development
- rollup-plugin-minify-html-literals ^1.2.6 development
- rollup-plugin-terser ^7.0.2 development
- rollup-plugin-typescript2 ^0.31.2 development