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.

Hi Rebecka, Could you please let me know how you got the .pos file from ETG-4000? Is it available even without using the digitization device during collecting the data?
Thank you in advance!