Using the flik-o-meter¶
This page is the operator's procedure: how to check that a design's targets flicker at the right frequencies, and the two specialised tests. What the results mean is on Interpreting results.
Flicker
Every test here shows flickering targets. Flicker can trigger seizures in people with photosensitive epilepsy; anyone with that history should not run or watch the tests. Esc in the stimulus window, or Abort in the dialog, stops a test at any time.
Before you start¶
- A built and flashed flik-o-meter, plugged into the PC that drives the display you want to check (Build guide).
- The real setup. Check on the display, PC, refresh rate and brightness the experiment will use, with the stimulus window fullscreen. A check on a different screen says nothing about this one.
- A normally lit room. The sensor needs a little room light around the tip (see Calibration). Avoid strong light falling directly on the screen.
- The design, open in the toolbox's Design mode, or saved as a manifest file for the command line.
Placing the sensor¶
Hold the wand like a fat marker and rest its soft ring lightly on the glass, with the snout inside the cued target's coloured outline. Don't press: LCD panels can be marked permanently. The cue is drawn as an outline so you can see it around the tip.
With the sync square option you don't move between targets at all: a full-contrast square in the bottom-left corner of the screen flashes at the frequency of whichever target is being measured, and you keep the sensor parked on it for the whole run. This is easier, and it removes any chance of a neighbouring target bleeding in. It checks the frequencies the display produces, but not the targets' own appearance, so it is the wrong choice for pattern-reversal designs (see below).
Checking a design's flicker (Measure flicker)¶
This is the routine check. It steps through every target in the design once.
- In Design mode, with the design you want to check in the form, click Measure flicker… at the foot of the centre pane, beside Preview flicker and Preview session. The check uses the design currently in the form, so you don't need to save it first; its report carries that design's fingerprint.
- Pick the serial port. The list says how many ports it found. A genuine Arduino Nano build (an FTDI FT232R USB chip, USB ID
0403:6001) is recognised and selected for you; any generic FT232R adapter is assumed to be the flik-o-meter. An OpenBCI Cyton dongle is labelled "NOT the flik-o-meter", and Start asks before measuring on it. Plugged it in after opening the dialog? Click Rescan; your choice is kept. "(no port - visual-only run)" runs the stimulus without a sensor. - Choose the options (all are explained in the table below). For most checks: Sync square on, tolerance 0.1 Hz, Calibrate timebase 60 s.
- Click Start. For the first minute the toolbox calibrates the board's clock, and no window appears: that is expected, not a hang, and the sensor can sit anywhere.
- The stimulus window opens. For each target in turn:
- the target is cued as a coloured outline around a black square, and all the others are black;
- place the sensor (on the target, or on the sync square) and press SPACE, or the wand's button if you ticked Advance with the on-device button (
--buttonon the command line); - all the targets flicker for the capture while the sensor records the cued one, and one line of results appears in the dialog.
- When the last target is done, the dialog prints how many targets passed and where the report was saved. Read Interpreting results before trusting a pass that carries a flag.
The same check from the command line:
python -m ssvep.stim.renderer path/to/design.json --measure-flicker --photodiode COM5 --fullscreen --sync-square
Use your port in place of COM5 (/dev/tty.usbserial-… on macOS). Leave out --photodiode for a visual-only run. With no manifest path it uses the toolbox's built-in example design. The command exits with status 0 when every target passed (or for a visual-only run) and 1 otherwise, so it can be scripted.
Options¶
| Dialog | Command line | What it does | When to change it |
|---|---|---|---|
| Sync square (bottom-left) | --sync-square |
Flashes a full-contrast square in the bottom-left corner at the cued target's frequency, as a fixed place to park the sensor | Turn it off for pattern-reversal designs, and when you want to check the targets themselves |
| Tolerance (Hz) | --tolerance |
How far the measured frequency may be from the design's and still pass (default 0.1 Hz) | Rarely |
| Calibrate timebase | --calibrate-s |
How long to measure the board's true sample rate before the first target (default 60 s; 0 skips it) | Don't shorten it; see Calibration |
| Dark reference first | --dark-reference |
Before the first target, captures the sensor with the screen held black, so the report can give each target's modulation depth and noise floor | For contrast and pattern-reversal checks; see Calibration |
| — | --stim-s |
Capture length per target, in seconds (default: the design's stimulation time) | Lengthen it for slow flicker. The dialog lengthens the capture by itself to fit the slowest target |
| Advance with the on-device button | --button |
Lets the wand's button start each capture instead of SPACE | When the wand has a button |
| — | --out-dir |
Where the report is written (default qc-reports/) |
Rarely |
If the design reverses a pattern, the dialog starts with Sync square off and Dark reference first on, and says before Start when no contrast figures will be reported. Turning the sync square back on asks you to confirm, because the square would bypass the pattern.
Pattern-reversal stimuli: measure one check¶
A contrast-reversing checkerboard or grating keeps the average light constant; that is the point of it. So a sensor that sees many checks sees no flicker at all. It has to sit inside one check (or one bar), where the light really does swing between black and white, and that needs an aperture narrower than a check.
- Run Measure flicker without the sync square: the sync square is a plain flash and would measure the frequency while bypassing the pattern.
- Use Dark reference first, so the report can say how fully each check reverses.
- Place the sensor on the centre of each target, as precisely as you can.
The toolbox ships two test designs built for this, qc-fixtures/run-manifests/flik-o-meter-checkerboard-reversal.json (four 3° checkerboard targets, 0.5 cycles per degree, 30–36 Hz) and qc-fixtures/run-manifests/flik-o-meter-grating-reversal.json (the same with a grating, on 4° targets). Both are made so that the centre of every target reverses fully. How precisely you must place the sensor is worked out in the technical reference.
A capture of a reversing pattern that shows no flicker usually means the sensor was misplaced or its aperture too wide, not that the stimulus is broken; the indistinguishable_from_dark flag says so.
Measuring marker-to-light latency from a recording¶
Measure flicker checks frequency, not timing: each capture starts when you press SPACE, so it cannot say how long after a "stimulus on" marker the light appears. That delay, in the amplifier's own timeline, is where an acquisition timing error shows up, and how much it varies from trial to trial matters for any analysis that depends on phase. It is measured from an ordinary recording, with the sensor's signal wired into the amplifier.
- Wire the light into the amplifier. Feed the flik-o-meter's analogue signal through a resistive divider into one amplifier channel, so a volt-level signal fits an EEG input (see the build guide's light output for an amplifier). This is a bench test: no participant is connected. Put the sensor on the single target.
- Record the latency test runs.
qc-fixtures/run-manifests/flik-o-meter-latency-10hz.jsonandflik-o-meter-latency-40hz.jsoneach show one square-wave target at fixation, starting at phase 0 after a black cue, so every onset is a dark-to-light edge, 40 times.qc-fixtures/session-protocols/flik-o-meter-latency-cyton.jsonruns each of them three times, interleaved, and the recorder starts a fresh amplifier connection for every run. For another amplifier: on Build Protocol, click Load protocol… and browse toqc-fixtures/session-protocols/(the builder then uses theqc-fixtures/run-manifests/folder beside it), apply your hardware with Set up acquisition hardware, and save under a new name. All three files are generated byscripts/build_latency_qc_manifests.py; re-run that rather than editing them. -
Extract the latencies. Pass every run of a series in one call:
--channelis the channel the light is on, by label or 1-based index. Each trial's marker is read against the light in that channel, using the waveform declared in the<base>.session.jsonfile saved beside each recording.--photodiode-stream NAMEalso measures a separate light stream, if the recording has one, and reports the per-trial difference between the two.
The output, qc-reports/light-latency_<time>.json plus a per-trial .tsv, is described on Interpreting results.
Related checks¶
- Measure refresh, in Design mode's Display section, measures the monitor's real refresh rate and needs no sensor. It characterises the screen on its own; Measure flicker checks what a particular design produces on it.
- The on-hardware test runbook for the acquisition PC (
docs/WINDOWS_TESTING.md) walks through a first bring-up of the renderer and the flik-o-meter together.