documentation / example / other / opm_straighthelmet /

Designing an OPM helmet with a straight opening at the bottom

If you design an OPM helmet on the basis of an individual MRI, you can end up with a helmet that “curves in” at the bottom which would make it impossible for the participant to actually slide their head in.

The following example code provides a solution by modifying the segmentation such that it extends in a straight direction towards the bottom. This results in a helmet with an opening at the bottom that is as wide as the widest point of the head.

This example follows the same design principle as the tutorial for designing a custom 3D printed OPM helmet. The anatomical MRI used in this example is available from our download server.

% read the anatomical MRI
mri = ft_read_mri('individual.nii');

% use the same realignment to the CTF coordinates as in the OPM helmet design tutorial
nas_vox = [ 102 217 123 ];
ini_vox = [ 90   18 104 ];
lpa_vox = [ 20  135 103 ];
rpa_vox = [ 173 121  95 ];

cfg = [];
cfg.method = 'fiducial';
cfg.coordsys = 'ctf';
cfg.fiducial.nas = nas_vox;
cfg.fiducial.lpa = lpa_vox;
cfg.fiducial.rpa = rpa_vox;
mri_realigned = ft_volumerealign(cfg, mri);

% reslice the MRI and place it nicely in the middle

cfg = [];
cfg.xrange = [ -97.5000 157.5000] - 30;
cfg.yrange = [-127.5000 127.5000];
cfg.zrange = [ -87.5000 167.5000] - 5;
mri_resliced = ft_volumereslice(cfg, mri_realigned);

% make the segmentation of the scalp surface

cfg = [];
cfg.output = 'scalp';
mri_segmented = ft_volumesegment(cfg, mri_resliced);

% construct a triangulated mesh for the scalp surface

cfg = [];
cfg.method = 'projectmesh';
cfg.numvertices = 4000;
headshape = ft_prepare_mesh(cfg, mri_segmented);

% make a copy of the segmentation, remove the lower part of the head

segmented_v1 = mri_segmented;
segmented_v1.scalp(:,:,1:50) = 0;

% inflate the segmentation to make an airgap and a helmet 

segmented_v1.airgap = imdilate(segmented_v1.scalp,  strel('sphere', 2)); % 2 mm air gap
segmented_v1.helmet = imdilate(segmented_v1.airgap, strel('sphere', 5)); % 5 mm thick helmet

% convert to indexed representation to allow for plotting as if it were "functional" data
segmented_v1 = ft_checkdata(segmented_v1, 'segmentationstyle', 'indexed');

% plot the segmentation of the headshape, airgap and helmet

cfg = [];
cfg.funparameter = 'tissue';
cfg.location = [0 0 0];
cfg.locationcoordinates = 'head';
cfg.atlas = mri_indexed;
cfg.funcolormap = [
0 0 0 % black
0 1 0 % green
1 0 0 % red
0 0 1 % blue
];
cfg.funcolorlim = [0 4];
ft_sourceplot(cfg, segmented_v1)

%%

% make a copy, remove the lower part of the head

segmented_v2 = mri_segmented;
segmented_v2.scalp(:,:,1:50) = 0;

% for each vertical column fill the segmentation from the bottom to the top

for i=1:segmented_v2.dim(1)
for j=1:segmented_v2.dim(2)
    column = segmented_v2.scalp(i,j,:);
    if ~any(column)
    continue
    else
    bottom = 50;
    top    = find(column, 1, 'last');
    segmented_v2.scalp(i,j,bottom:top) = 1;
    end
end % for j
end % for i

% inflate the segmentation to make an airgap and a helmet. same as before

segmented_v2.airgap = imdilate(segmented_v2.scalp,  strel('sphere', 2)); % 2 mm air gap
segmented_v2.helmet = imdilate(segmented_v2.airgap, strel('sphere', 5)); % 5 mm thick helmet

% convert to indexed representation to allow for plotting as if it were "functional" data
segmented_v2 = ft_checkdata(segmented_v2, 'segmentationstyle', 'indexed');

% plot the segmentation of the headshape, airgap and helmet

cfg = [];
cfg.funparameter = 'tissue';
cfg.location = [0 0 0];
cfg.locationcoordinates = 'head';
cfg.atlas = mri_indexed;
cfg.funcolormap = [
0 0 0 % black
0 1 0 % green
1 0 0 % red
0 0 1 % blue
];
cfg.funcolorlim = [0 4];
ft_sourceplot(cfg, segmented_v2)

% make a triangulated surface mesh of the headshape, airgap and helmet

cfg = [];
cfg.method = 'projectmesh';
cfg.numvertices = 4000;
headshape_v2 = ft_prepare_mesh(cfg, segmented_v2);

helmet_inside  = headshape_v2(1); % this is the "airgap" surface
helmet_outside = headshape_v2(2); % this is the "helmet" surface
modified_headshape = headshape_v2(3); % this is the modified headshape

% plot the triangulated surface mesh of the original headshape, with the inside of the helmet

figure
ft_plot_mesh(headshape, 'facecolor', 'skin', 'edgecolor', 'none');
ft_plot_mesh(helmet_inside, 'facecolor', 'lightblue', 'edgecolor', 'none', 'facealpha', 0.4);
ft_headlight

Following this, you would continue with the placement of the electrodes and OPM sensors on the modified headshape as in the tutorial on designing a custom 3D printed OPM helmet.