What approaches should take for artifacts detection and preprocessing?

I am using visual studio with versions:

  • Python version: 3.10.2
  • MNE version: 0.24.1
  • operating system: Windows 10

I am a novice user of python and mne packages. I am stuck in my fnirs data analysis for more than one week. And I do not know what approaches should I take next. If somebody please help me, I would be grateful to you.

I am converting a csv file to raw intensity file following this link: Importing data from fNIRS devices — MNE 0.24.1 documentation

And my code is:

data = pd.read_csv("../data/Participant_793.csv", header = None)
ch_names = ['S1_D1 O2Hb', 'S1_D1 HHb', 'S1_D1 tHb', 'S1_D1 HbDiff',
            'S2_D1 O2Hb', 'S2_D1 HHb', 'S2_D1 tHb', 'S2_D1 HbDiff',
            'S3_D1 O2Hb', 'S3_D1 HHb', 'S3_D1 tHb', 'S3_D1 HbDiff',
            'S4_D1 O2Hb', 'S4_D1 HHb', 'S4_D1 tHb', 'S4_D1 HbDiff',
            'S5_D2 O2Hb', 'S5_D2 HHb', 'S5_D2 tHb', 'S5_D2 HbDiff',
            'S6_D2 O2Hb', 'S6_D2 HHb', 'S6_D2 tHb', 'S6_D2 HbDiff',
            'S7_D2 O2Hb', 'S7_D2 HHb', 'S7_D2 tHb', 'S7_D2 HbDiff',
            'S8_D2 O2Hb', 'S8_D2 HHb', 'S8_D2 tHb', 'S8_D2 HbDiff']
ch_types = ['fnirs_cw_amplitude'] * 32

sfreq = 50.  # in Hz
info = mne.create_info(ch_names=ch_names, ch_types=ch_types, sfreq=sfreq)
raw = mne.io.RawArray(data, info, verbose=True)

After that, I tried to follow these two links: Overview of artifact detection — MNE 0.24.1 documentation
Preprocessing functional near-infrared spectroscopy (fNIRS) data — MNE 0.24.1 documentation

Unfortunately, both of the links do not work for me. I could not find optode distances rather it provided an error

Even I could not make a raw intensity to optical density conversion. It gave an error

Hi @pronob, I never did fNIRS, but I would assume you need channel positions to compute any kind of distance. Did you follow this part of the tutorial?

Thanks for your response. I have a different csv data file that contains some optode coordinate (x,y,z) values. But I am not sure what can I do with this information? Also, how can I put the locations when importing the original csv data file? Do you have any idea? I will appreciate any help here.

@pronob
You would have to construct a Montage (and the apply it to your data) either by:

  • reading the coordinate file via mne.channels.read_custom_montage
  • you could also read the coordinates yourself and construct the montage using mne.channels.make_dig_montage

the first option should be easier.

image
image

This is my optode location data in csv format. I am new to python. When I used the mne.channels.read_custom_montage function I got an error: could not convert string to float: ‘’

I do not understand how to read this data and merge this with raw intensity data. Could you please assist me here?

I’m not sure I will be able to help - I never worked with fNIRS data so I’m not sure if my suggestion will work well for you. Anyway, I would do something like this:

  1. first copy the location file and modified it so that it doesn’t have and blank lines or repeated column names

  2. give simple names to columns, for example: name, x, y, z

  3. save the file as .csv and read it to python using pandas:

    import pandas as pd
    locs = pd.read_csv(full_file_path)
    
  4. Make sure what are the units of the x, y, z channel positions. Mne requires meters, while yours might be in mm. You can convert between units by multiplying or dividing the x, y, z columns:

    locs.loc[:, ['x', 'y', 'z']] *= scaling_factor
    
  5. Then you could use mne.channels.make_dig_montage to construct the montage, but you would first have to put the fiducials aside. So assuming they are the first five rows in the table you could do:

    fids = locs.loc[:4, :]
    locs = locs.loc[5:, :]
    lpa = fids.query('name == "LPA"')[['x', 'y', 'z']].values
    rpa = fids.query('name == "RPA"')[['x', 'y', 'z']].values
    nasion = fids.query('name == "Nz"')[['x', 'y', 'z']].values
    
    locs_dict = {row.name: row[['x', 'y', 'z']].values for _, row in locs.iterrows()}
    montage = mne.channels.make_dig_montage(locs_dict, lpa=lpa, rpa=rpa, nasion=nasion)
    

Then you could apply the montage. Some things may not work, as I didn’t test this code. Also - there may be an esier way to do it, like reformatting your file to fit one of the standard location formats that mne can read. But unfortunatelly I don’t know these formats, so I can’t tell you how to reformat the file.