WizardHat

From montageto printed cap.

The generated cap draped on the design head.

One desktop application: design an fNIRS or hybrid EEG–fNIRS montage on the head, turn it into a ninjaCap-style cap for a head size, and export the panels and the probe files as one folder that says how it was made.

Adam Emile Askeshowcase · 0.0.6
the problem

Why we left the textile cap

A textile cap

  • Holds a montage only where the grommets are sewn in.
  • Gives us no standard way to high-density fNIRS.
  • Needs a custom solution for every EEG integration.
  • Gets hot after a long session, worse with a lot of hair.

A printed cap

  • Takes any montage, because a holder is printed wherever the montage puts one.
  • Takes EEG electrodes in the same print, for a hybrid cap.
  • Is an open lattice, so air reaches the head.
The printed lattice close up: hexagonal struts and ring holders.

The printed lattice: open hexagons and a ring holder at every optode.

where it comes from

Two tools, then one

The Montage Creator's top view over the 10-5 grid.

NIRWizard's Montage Creator

  • Built to replace NIRSite. It designs a montage and writes the folder Aurora loads.
  • Cannot make a cap.
A whole-head cap from AdeptCap, panels coloured, on the head model.

AdeptCap, ninjaCap reimplemented

  • von Lühmann et al. (2024) generate caps on a cloud compute cluster and weld the panels ultrasonically. We have no ultrasonic welder.
  • AdeptCap, our independent reimplementation, runs on a laptop and joins the panels with printed pins.
WizardHat puts the two in one application: design the montage, make the cap, export both.
Grommet bore offset against BU's caps, per panel, for a frontotemporal and a whole-head cap at 54, 56 and 58 cm.

Grommet bore offset from BU's own caps, per panel. Two montages, three sizes, 18 panels, the same bore detector on both.

the engine

Checked against BU's caps

  • Median bore offset 0.59 mm, under one 0.6 mm line width.
  • Side panels 0.4–0.8 mm: outline, ear slit and pads overlay.
  • Mid strip up to 1.2 mm, because ours is 1 % longer.
  • WizardHat's engine is this one, ported to Rust at parity and run inside the app.
the joint

Panels that snap, no welder

The paper fuses 2 mm tabs with a 57 kHz ultrasonic clamp. Ours snap together.

The pin-snap joint: a 3 mm pin with a mushroom head, and the eyelet over it.

A 3 mm pin with a mushroom head on one panel; the eyelet on the other snaps behind the head. It prints flat, with no supports.

A test coupon: pin strip and eyelet strip, flat and assembled.

A coupon: a pin strip and an eyelet strip across a straight seam. Coupons like it tested clearances of 0.0, 0.2 and 0.4 mm; WizardHat uses 0.4 mm by default.

The application

Six stages on one rail, followed with Anderson-HD, a recreation of the high-density multidistance montage of Anderson et al. (Neurophotonics, 2025): 25 sources and 58 detectors, from the head to the export folder.

the flow

The stage rail

Each stage reports what it holds. Change a stage and every stage after it is marked stale.

1

Montage

On the head or flat on the mat; the channels follow.

2

Cap facts

Grommet types, rotation, anchors, rigid springs.

3

Head and size

Circumference, print bed, cap profile.

4

Generate

The engine runs; every grommet and joint gets a status.

5

Preview

Flat on the bed, draped on the head.

6

Export

One folder: panels, probe files, the cap file, the pattern.

1 · montage

Design on the head

  • A top view over the 10-5 grid, and the same montage on the 3-D head beside it.
  • 25 sources and 58 detectors, on the 10-5 points or placed free anywhere on the scalp, with a drag to move them. A channel rule derives 206 channels, 16–34 mm.
  • NIRSport2 port accounting, mirror, auto-fill, undo and redo.
  • The Montage Creator is NIRWizard's, ported with its tests.
The Montage stage: the Anderson-HD montage on the top view and on the 3-D head.
1 · montage, flat

Or flat on the mat

  • A patch designed in millimetres from nodes, springs, anchors and dummies, the way AtlasViewer's SDgui works, and registered onto the scalp.
  • Nodes typed into tables or pasted from a spreadsheet; springs added by length in one step; a selection moved, flipped, mirrored or duplicated; renumbered by position.
  • An AtlasViewer .SD opens as a patch, including one that holds its probe only on the head.
  • Anderson-HD on the mat has 8 dummies, 390 springs and 9 anchors.
Flat mode: the Anderson-HD patch on the cutting mat, its source table, and the registered montage on the head.
1 · montage, hybrid

Electrodes in the same print

  • A third role beside the optodes, for a hybrid EEG–fNIRS cap.
  • An electrode gets a ring holder, #GTEC1, the g.tec g.Nautilus holder, and goes through the engine like an optode. Its number is its channel.
  • The export writes BIDS electrodes.tsv and coordsystem.json beside the fNIRS files.
  • The screenshot is Sensorimotor 16 × 16 with 16 electrodes between its 42 channels.
The Sensorimotor 16×16 montage with 16 EEG electrodes between its optodes, in the top view and on the head.
1 · montage, the figure

The montage, as a figure

Exported from the Montage stage as SVG or PNG, with a transparent variant, for the methods section.

Montage figure: Sensorimotor 16×16 with 16 electrodes, numbered by optode.

Sensorimotor 16 × 16 with 16 EEG electrodes, numbered by optode.

Montage figure: Anderson-HD, 25 sources and 58 detectors, every optode numbered.

Anderson-HD: 25 sources, 58 detectors, 206 channels.

Montage figure: the hybrid montage with its 42 channels numbered.

The same hybrid montage, numbered by channel.

2 · cap facts

The cap lives in the montage

  • What the engine can print: #NIRX2 holders, #PMRK1 markers, #GTEC1 electrode holders, from the engine's own grommet library.
  • Per site: grommet type, rotation, anchor.
  • Rigid springs: here all 206 channels.
  • All of it is saved in the .nirwmontage, with the montage.
The Cap facts stage: grommet types and the per-site table.
3 · head and size

Size, bed, joints

  • Head circumference, 50 to 65.5 cm. This deck follows one size: 60 cm.
  • The print bed: a Bambu Lab H2D, 320 mm. The engine splits the top panel when it is wider than the bed.
  • The cap profile: pin-snap joints, a printed pin that snaps into an eyelet; the seam hold; the bore, ring height and strut width.
The montage is designed on the ICBM 2009c symmetric average, and the cap is generated on that same head, scaled to the cap's size.
The Head and size stage: the design head, the circumference, a 320 mm bed and the cap profile.
3 · the tuner

Every value of the engine, in one text

  • Every physical value of the engine is a key of one YAML text.
  • Edited in the Tuner tab, with the default beside each key and errors on their line.
  • Head and size edits seven of these keys in the same text; the Tuner reaches the rest.
  • This cap has a 1.3 mm strut, the #NIRX2 bore at 8.9 mm and a ring joint on the seam.
The Tuner tab: the engine's values as YAML, each with its default and a comment.
4 · generate

Run the engine

  • The engine runs inside the app, step by step: flatten the head, build the panels, register the probe, place the grommets and the joints, build the meshes.
  • Every grommet gets a panel and a status: all 83 placed, two of them called out near a panel's edge.
  • Joints get theirs too: 100 pin-snaps at 60 cm, with the seams that keep a gap called out.
  • The first cap of a head size takes about half a minute, the next ones a few seconds. The cap is drawn on the head as soon as it is done.
The Generate stage: all 83 grommets placed, and the cap drawn on the head in a colour per panel.
5 · preview

Flat on the bed

  • The four panels on the cutting mat, at one scale. The ruler reads true on it.
  • Each panel against the bed: sideLeft 237 × 240 mm, sideRight 236 × 241, top1 83 × 190, top2 84 × 190. All four fit 320 mm.
  • A panel that fits only turned is said to, and turned in the slicer.
The Preview stage, flat on the bed: four panels on the cutting mat.
5 · preview

Draped on the head

  • The lattice, grommets and joints put back on the head, as the cap will be once assembled.
  • The same head the montage was designed on, scaled to 60 cm.
  • The stage says how much lies outside the flattened head: 30 % here, the tabs, the ear pieces and what a seam hold prints past its seam.
The Preview stage, draped: the cap lattice on the design head.
6 · export

One folder, written whole

  • Panels as STL, as the engine made them.
  • The montage as the NIRSite folder Aurora loads, a probe-only SNIRF, and the .nirwmontage the cap was made from.
  • cap.yaml: every parameter the cap was generated with. pattern.svg: every piece at 1:1, a record of the cap.
  • For a hybrid cap, eeg/ with the BIDS electrode positions. README.txt: what agrees with what, in words.
The Export stage: what is exported, what agrees with what, and the last export's 16 files.

A cap that says how it was made

One real export, Anderson-HD at 60 cm, opened file by file.

the export · the folder

anderson-export/

panels/printable
sideLeft.stl237 × 240 × 6.2 mm
sideRight.stl236 × 241 × 6.2 mm
top1.stl83 × 190 × 3.3 mm
top2.stl84 × 190 × 3.3 mm
nirsite/Aurora loads it
Standard_probeInfo.mat · .aux28 kB
Standard_Optodes.txt · _Channels.txt83 · 206
digpts.txt · probeInfo.json · sidecar
Anderson-HD-test.snirfprobe only
Anderson-HD-test.nirwmontagewith its cap facts
cap.yamlthe resolved cap file
pattern.svgevery piece at 1:1
README.txtwhat agrees with what
16
files
one folder, written whole
4
panels
175 388 triangles of binary STL
83
grommets
25 sources, 58 detectors, all placed
206
channels
named the same in every file
the export · cap.yaml

Every parameter, and who set it

# Resolved cap file (format 1): every parameter, # no profile reference. probe: Anderson-HD-test.nirwmontage sd: "design head" # default head_circumference_cm: 60.0 # app bed_size_mm: 320.0 # app overrides: print: line_width_mm: 0.6 # default strut_width_mm: 1.3 # cap profile joint: type: "pin-snap" # app clearance: 0.4 # app seam_hold: "ring-joint-v2" # cap profile grommets: "#NIRX2": { bore_d: 8.9, height: 1.3, … } # cap profile … 75 values in all resolved: montage_sha256: "72484ba6…b569c7" head_model_sha256: "14804238…d8ed93" engine: "wh-cap 0.0.6"
64
default
the engine's own value, written out anyway
4
cap profile
the profile's values: strut, seam hold, bore, ring height
7
app
chosen in the app: size, bed, joint, clearance, the cache…
The file holds values, not a reference to a profile. If a default changes next year, this file still says what this cap was made with.
the export · the hash chain

The cap names its montage by content

Anyone with the folder can check it with sha256sum. WizardHat is not needed.

$ sha256sum Anderson-HD-test.nirwmontage 72484ba60f8b8bfecc8cf34b8b8228318989dbdbf355ff310ace2e5c5eb569c7 Anderson-HD-test.nirwmontage $ grep -A3 resolved: cap.yaml resolved: montage_sha256: "72484ba60f8b8bfecc8cf34b8b8228318989dbdbf355ff310ace2e5c5eb569c7" head_model_sha256: "148042383c5d948d1e9b006b611d166b32149bc7dec1153c6c06b513c0d8ed93" engine: "wh-cap 0.0.6"

The montage

The exact file the cap was generated from, cap facts included, hashed.

The head

The design head the cap was made on, hashed. The same hash at every size.

The engine

The engine the panels came from, by name and version.

the export · what agrees with what

One head, by position

  • Every file names the same optodes, the same numbers and the same channels.
  • The probe files hold positions on the design head. The cap was made on the same head, scaled to 60 cm, with the probe registered on it at that size.
  • Mapped back to the design head, a grommet lies where its optode lies in the probe files, up to what the registration at the cap's size moves it.
  • So the README says: the cap and the probe files agree by position, on one head.
README.txt What agrees with what The cap and the probe files agree by position, on one head. Every file of this folder names the same optodes, the same numbers and the same channels. The positions in the probe files are on the design head. The cap was made on the same head, scaled to the cap's size.
The design head is the ICBM 2009c symmetric average in MNI millimetres, the head NIRSite's ICBM152 positions describe. It ships with the app, so there is no head file to set.

Where it stands

0.0.6, and what comes next.

where it stands

Done, and next

In 0.0.6

  • Montage to exported folder, in one window: on the head, flat on the mat, or from an AtlasViewer .SD.
  • The engine in Rust, inside the app, so the Linux and Windows installers need nothing else.
  • One design head, so the cap and the probe files agree by position.
  • EEG electrodes for hybrid caps, with BIDS positions in the export.

Next

  • A cap printed on the new design head, and the seam holds checked on a real print.
  • Subject heads from MRI.

On the bench

  • A full cap in TPU, assembled with pin-snaps, no glue.
  • Placement accuracy on a printed head, against the paper's 2.7 mm.
The printable validation head with dimples at the 10-20 positions.
The matching validation cap on the head.
references

What this deck builds on

The cap method

von Lühmann A, Kura S, Joseph O'Brien W, Zimmermann BB, Duwadi S, Rogers D, Anderson JE, Farzam P, Snow C, Chen A, Yücel MA, Perkins N, Boas DA. ninjaCap: a fully customizable and 3D printable headgear for functional near-infrared spectroscopy and electroencephalography brain imaging. Neurophotonics. 2024 Jul;11(3):036601. doi: 10.1117/1.NPh.11.3.036601. PMID: 39193445; PMCID: PMC11348010.

AdeptCap, the engine in WizardHat, is our independent reimplementation of this method. It joins the panels with printed pins instead of welds and runs on a laptop.

The Anderson-HD montage

Anderson JE, Carlton LB, Kura S, O'Brien WJ, Rogers D, Rahimi P, Farzam PY, Zaman MH, Boas DA, Yücel MA. High-density multidistance fNIRS enhances detection of brain activity during a word-color Stroop task. Neurophotonics. 2025 Jul;12(3):035010. doi: 10.1117/1.NPh.12.3.035010. PMID: 40917100; PMCID: PMC12412631.

The montage in this deck is that study's montage, placed again by hand in WizardHat. It is not the authors' file.

WizardHat

Questions?

Adam Emile Aske

AdeptCap is our independent reimplementation of the ninjaCap method (von Lühmann et al., Neurophotonics 2024), with snap-together panels and local generation.