How to set ch_names using set_montage and DigMontage of 3x5 (ETG-7000) layout

  • MNE version: dev 1.2.
  • operating system: Windows 10

Hi I used Digmontage in order to create a montage out of a .pos file (positional file). However, I seem to not have named them correctly.
I did the following:

raw = read_hitachi(['Data/S11/S11_MES_Probe1.csv', 'Data/S11/S11_MES_Probe2.csv'])
print(raw.ch_names) 
"""
['S1_D1 695', 'S1_D1 830', 'S2_D1 695', 'S2_D1 830', 'S2_D2 695', 'S2_D2 830', 'S3_D2 695', 'S3_D2 830', 'S1_D3 695', 'S1_D3 830', 'S4_D1 695', 'S4_D1 830', 'S2_D4 695', 'S2_D4 830', 'S5_D2 695', 'S5_D2 830', 'S3_D5 695', 'S3_D5 830', 'S4_D3 695', 'S4_D3 830', 'S4_D4 695', 'S4_D4 830', 'S5_D4 695', 'S5_D4 830', 'S5_D5 695', 'S5_D5 830', 'S6_D3 695', 'S6_
D3 830', 'S4_D6 695', 'S4_D6 830', 'S7_D4 695', 'S7_D4 830', 'S5_D7 695', 'S5_D7 830', 'S8_D5 695', 'S8_D5 830', 'S6_D6 695', 'S6_D6 830', 'S7_D6 695', 'S7_D6 830', 'S7_D7 695',
'S7_D7 830', 'S8_D7 695', 'S8_D7 830', 'Mark', 'BodyMovement', 'RemovalMark', 'PreScan', 'S9_D8 695', 'S9_D8 830', 'S10_D8 695', 'S10_D8 830', 'S10_D9 695', 'S10_D9 830', 'S11_D9
 695', 'S11_D9 830', 'S9_D10 695', 'S9_D10 830', 'S12_D8 695', 'S12_D8 830', 'S10_D11 695', 'S10_D11 830', 'S13_D9 695', 'S13_D9 830', 'S11_D12 695', 'S11_D12 830', 'S12_D10 695'
, 'S12_D10 830', 'S12_D11 695', 'S12_D11 830', 'S13_D11 695', 'S13_D11 830', 'S13_D12 695', 'S13_D12 830', 'S14_D10 695', 'S14_D10 830', 'S12_D13 695', 'S12_D13 830', 'S15_D11 69
5', 'S15_D11 830', 'S13_D14 695', 'S13_D14 830', 'S16_D12 695', 'S16_D12 830', 'S14_D13 695', 'S14_D13 830', 'S15_D13 695', 'S15_D13 830', 'S15_D14 695', 'S15_D14 830', 'S16_D14
695', 'S16_D14 830']
"""

# return DigMontage 
montage11 = self_montage(file_path='Data/S11/0001.pos', csv_file='Data/S11/0001_edit.csv') 

the function self_montage just reades the pos.file and creates the right format in order to use make_dig_montage (ch_pos, nasion, lpa, rpa, hsp (none), hpi (none), coord_frame = β€˜mri’. It also writes the ch_names and their x,y,z coordinates to the csv-file: 0001_edit.csv.

The 0001_edit.csv looks the following way:

ch_name,x,y,z
S1,51.1,47.9,54.4      # left hemisphere start
D1,63.2,21.9,53.0
S2,69.6,-6.1,46.2
D2,70.0,-33.8,43.7
S3,63.4,-61.4,35.1
D3,51.4,40.5,77.7
S4,61.5,17.4,72.6
D4,68.3,-9.4,69.4
S5,66.5,-37.0,64.9
D5,62.3,-64.2,59.1
S6,44.2,35.9,96.1
D6,55.5,11.3,96.6
S7,60.2,-15.5,97.0
D7,57.5,-43.0,91.1
S8,46.2,-71.1,86.2    # left hemisphere ends  - 15 optodes 
S9,-66.0,-67.1,30.8   # right hemisphere starts
D9,-73.6,-40.3,38.7
S10,-78.0,-15.3,45.3
D10,-74.8,14.4,54.3
S11,-67.1,39.2,60.0
D11,-68.0,-72.2,50.9
S12,-75.0,-47.6,60.3
D12,-77.9,-19.7,69.4
S13,-75.1,4.8,74.1
D13,-67.5,27.2,79.9
S14,-58.0,-76.7,79.2
D14,-68.0,-54.2,84.9
S15,-73.5,-26.6,92.2
D15,-71.9,-3.4,97.7
S16,-61.0,21.5,104.2  # right hemisphere ends - 15 optodes 

The setup should follow: 5x3 optodes (15 on each side) - source (blue), detector (green)
left-hemi setup:

Now when I try:

raw.set_montage(montage11, match_case=True, match_alias=True, on_missing='ignore')

I get the following Error message: ValueError: β€˜D8’ is not in list, which makes sense cause I do not have D8, but I am not sure how to prevent this as I only have 15 optodes on each side.

Thank you in advance for your support! :raised_hands:t2: :muscle:t2:
Best,
Rebecka

In your print out of channel names, I see

..., 'S9_D8 695', 'S9_D8 830', 'S10_D8 695', 'S10_D8 830', ... 'S12_D8 695', 'S12_D8 830', ...

in other words your data does think that there was a detector called D8. Here are all the sources/detectors that appear in the channels list:

foo = list(filter(lambda x: x.startswith('S'), raw.ch_names))
bar = list(map(lambda x: x.split()[0].split('_'), foo))
baz = sorted(set(x for y in bar for x in y))
# result is 
# ['D1', 'D10', 'D11', 'D12', 'D13', 'D14', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7',
#  'D8', 'D9', 'S1', 'S10', 'S11', 'S12', 'S13', 'S14', 'S15', 'S16', 'S2', 'S3',
#  'S4', 'S5', 'S6', 'S7', 'S8', 'S9']

There are indeed 30 items in that list, so probably something is wrong with your self_montage() function? If you want further help please provide the data files, pos file, and the content of the self_montage() function.

cc @rob-luke : is it common to need to mangle the .pos file in order for MNE-Python to use it? If so maybe we could try to find ways to make that easier.

1 Like

Thank you so much for your support! :raised_hands:t2: I really had the mistake in my own function where I incorrectly renamed them after the .pos file extraction. After renaming them according to your presented list it seems to work! Thanks :smiley:

Wonderful, I am glad to hear it works.

Please let us know if we can update the documentation to make this clearer for future users.

1 Like

Where does the pos file come from? Is this exported by the fNIRS vendor software or something custom you made?

1 Like

Yes, the .pos file is format generated by the Hitachi ETG-4000 software. The digitisation device is an integrated Polhemus Patriot (Polhemus Patriot). I do not know if the .pos file is the same format as the Polhemus software though.