{"id":18110690,"url":"https://github.com/coganlab/two_beep_eeg_sourcelocalization","last_synced_at":"2025-04-06T07:45:19.531Z","repository":{"id":130535470,"uuid":"555554567","full_name":"coganlab/Two_Beep_EEG_SourceLocalization","owner":"coganlab","description":null,"archived":false,"fork":false,"pushed_at":"2022-11-02T19:37:45.000Z","size":2803,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-02-12T13:24:08.819Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://coganlab.pages.oit.duke.edu/wiki/","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coganlab.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-21T20:21:11.000Z","updated_at":"2024-04-30T15:21:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"0aa3d2ee-e2ed-4d93-adaf-040cb529bbe6","html_url":"https://github.com/coganlab/Two_Beep_EEG_SourceLocalization","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coganlab%2FTwo_Beep_EEG_SourceLocalization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coganlab%2FTwo_Beep_EEG_SourceLocalization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coganlab%2FTwo_Beep_EEG_SourceLocalization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coganlab%2FTwo_Beep_EEG_SourceLocalization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coganlab","download_url":"https://codeload.github.com/coganlab/Two_Beep_EEG_SourceLocalization/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247451621,"owners_count":20940946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-01T00:11:02.845Z","updated_at":"2025-04-06T07:45:19.512Z","avatar_url":"https://github.com/coganlab.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# I RECOMEND YOU USE JUPYTER NOTEBOOK\n\nLINUX SETUP:\n1. Install freesurfer and mne onto your ubuntu\n\ta. make sure that you change your freesurfer environment variables to the folders you want them to be (on the shared drive between the linux distrib and the PC)\n\t\tExample:\n\t\t\texport FREESURFER_HOME=/share/freesurfer \n\t\t\texport SUBJECTS_DIR=$FREESURFER_HOME/subjects \n\t\t\tsource $FREESURFER_HOME/SetUpFreeSurfer.sh\n\t\tRecomended - Select Shared or Box Folder\n\n2. Install Xserver follow this website: _______\n3. install anaconda-navigator or conda onto your linux distrib\n4. Activate mne (conda activat mne)\n5. open the gui for the navigator \n6. switch to the MNE driver\n7. open spyder and a jupyter qt console\n8. open a second Linux distrib to do coregistration\n9. copy and paste all code from document into jupyter qt console\n10. type %matplotlib qt --\u003e allows for graphs to display\n11. get environment variables so mne can work with yout FreeSurfer data\n\ta. FREESURFER_HOME = os.getenv('FREESURFER_HOME')\n\tb. SUBJECTS_DIR = os.getenv('SUBJECTS_DIR')\n12. for 3D plotting do the following:\n\ta. mne.viz.set_3d_backend('pyvista')\n\tb. Export MNE_3D_OPTION_ANTIALIAS=false OR  mne.viz.set_3d_options(antialias=False)\n\t\t*Turns antialiasing*\n\n'E15','E16','E18','E20','E25','E35' - best\n\nPIPELINE:\n\n1. Given your specific subject, create 2 new folders in their sub folder:\n\tDigitization - used for Localization\n\tEpochs - used for making the BEM\n\nCLEAN DATA: *check out make_montage and change what files you traverse to based on your user and file structure*\n\n\t1. find Montage file (captrak) and load in EEG data and align it to correct channels\n    montage, raw = make_montage()\n\n\t2. Common Average Reference and select noisy channels\n    raw2 = set_data(raw, montage) #common average reference\n\n\t3. Save Captrak file to raw EEG file and then save it as a .fif\n    raw2.save(pathlib.Path('/mnt/d/Aidan/' + patient + '/Digitization') / 'Captrak_Digitization.fif', overwrite = True)\n\n\t4. Check to see if you chose the right channels\n    epochs = erp(raw2, montage)\n\n\t5. Run autorejection algorithms to detect noisy correlated epochs\n    epochs_ar = autorej(epochs)\n\n\t6. Run an ICA on the autorejection data\n    ica = ICA_auto_rej(epochs_ar)\n    ica.plot_sources(raw2, show_scrollbars=True)     # to plot ICA vs time\n\n\n\t7. Remove ICA channels that correspond to artifacts\n    ica.exclude = [0,1,2,5] # MANUAL INPUT\n\n\t8. Identify channels correlated with EOG data and remove them\n    reconst_evoked, reconst_raw = EOG_check_ar(epochs_ar, ica)\n\n\t9. save cleaned file as evoked data to correct folder\n    mne.write_evokeds('/mnt/d/Aidan/Grand_Averages/Epochs/' + subj + '_raw_for_ave.fif', reconst_evoked) #to do co-registration, have to do file path so gui.coreg can take as input\n\n\t10. save raw file\n    cd grand_averages\n    cd epochs\n    reconst_raw.save(subj + '_reconst_raw.fif')\n    cd ..\n    cd ..\n\n\nCoregistration:\n\t*to create a epochs_for_source_epo.fif file you first need to run covariance()*\n\t1. in qtconsole generate a bem\n\t\tepoch_data = '/mnt/d/'INSERT USERNAME'/'INSERT PATIENT OR SUBJECT'/Epochs/epochs_for_source_epo.fif'\n\t\t\ti.e. epoch_data = '/mnt/d/Aidan/E46/Epochs/epochs_for_source_epo.fif'\n\n\t\tepoch_info = mne.io.read_info(epoch_data)\n\n\t\tmne.bem.make_watershed_bem(subject=subj, subjects_dir=SUBJECTS_DIR, overwrite=True, volume='T1')\n\t\t\n\t2. Display bem\n\t\tmne.viz.plot_bem(subject = subj, subjects_dir = SUBJECTS_DIR, orientation = 'coronal')\n\t\t\n\t3. Double Check your file has fiducials\n\t\tmne.coreg.get_mni_fiducials(subj, SUBJECTS_DIR)\n\t\t\n\t4.Now open a new Ubuntu command line and activate mne\n    \t\tconda activate mne\n\n\t5. Perform Coregistration\n    \t\ttype mne coreg into your Linux distribution\n\t\tmake sure your digitization bem files are the same\n\t\tthen click where your fiducials should be\n\t\tthen hit fit fiducials\n\n\t6. save the Coregistration data as a trans.fif file\n\t\thit the button on the coregistration gui (bottom right)\n\nLocalization: (you can do this half of the pipeline with epoched or evoked data, I used evoked)\n\n\t1. generate Noise covariance and baseline evoked data\n    \t\tnoise_cov, fig_cov, fig_spectra, evoked = covariance(reconst_raw)\n\t\t\t- you can read in the raw:\n\t\t\t\treconst_raw = mne.io.read_raw_fif('/mnt/d/Aidan/Grand_Averages/Epochs/' + subj + '_reconst_raw.fif')\n\n\t2. double check your patient is your current subject: i.e. E46\n\t\tsubj\n\n\t3. define a path to traverse to your subjects given digitization info\n\t\tdata_path = '/mnt/d/Aidan/' + subj + '/Digitization'\n\n\t4. save your digitization data to a specific variable\n\t\tdata = pathlib.Path(data_path) / 'Captrak_Digitization.fif'\n\n\t5. read in that data from the file\n\t\ta. use baseline evoked\n\t\t\tinfo = mne.io.read_info(data)\n\t\tb. or use the evoked data you have already generated\n\t\t\tinfo = reconst_evoked.info\n\t\tc. or read in cleaned evoked\n\t\t\treconst_evoked = mne.read_evokeds('/mnt/d/Aidan/Grand_Averages/Epochs/' + subj + '_raw_for_ave.fif')\n\t\t\tinfo = reconst_evoked[0].info\n\t\t\t\n\t6. read in your coregistration data\n\t\ttrans = pathlib.Path(data_path)/ (subj + '-trans.fif')\n\t\ta. if your subjects MRI wasn't done correctly and you used the fsaverage brain\n\t\t\ttrans = pathlib.Path(data_path)/ ('fsaverage-trans.fif')\n\n\t7. plot your coregistration data just to double check\n\t\tfig = mne.viz.plot_alignment(info=info, trans=trans, subject=patient, subjects_dir=SUBJECTS_DIR, dig=True, verbose=True)\n\n\t8. compute your space (2D) - oct4, oct5 or oct6 are recommended (these determine the number of sources), you can also change the 'conductance' (then save to the correct folder of your choice) \n\t\tsrc = mne.setup_source_space(subject=subj, spacing='oct5', subjects_dir = SUBJECTS_DIR)\n\t\tcd Patient_SRC\n\t\tsrc.save(subj + '-src.fif',overwrite = True)\n\t\tcd ..\t\t\n\t\ta. or read it in\n\t\t\tsrc= mne.read_source_spaces('/mnt/d/Aidan/Patient_SRC/' + subj+ '-src.fif')\n\n\t9. you can now display this alignment as well with your coregistration\n\t\tmne.viz.plot_alignment(info=info, trans=trans, subject=subj, src=src, subjects_dir=SUBJECTS_DIR, dig=True)\n\n\t10. Generate a BEM model\n\t\tmodel = mne.make_bem_model(subject=subj, subjects_dir=SUBJECTS_DIR)\n\t\ta. if you use the fsaverage brain\n\t\t\tmodel = mne.make_bem_model(subject='fsaverage', subjects_dir=SUBJECTS_DIR)\n\n\t11. Create a BEM 'solution'\n\t\tbem_sol=mne.make_bem_solution(model)\n\t\t\t*note* this takes a while\n\t\ta. or load it in\n\t\t\tbem_sol = mne.read_bem_solution('/mnt/d/Aidan/' + subj+ '/Digitization/' + subj+ '_bem.fif')\n\n\t12. Create a forward solution(mindist = ignore elcetrodes minimum distance from skull, n_jobs =  of jobs to run in parallel when computing, ignore_ref=True  can be used to ignore reference electrode (Common Average Reference))\n\t\tfwd = mne.make_forward_solution(info, trans=trans, src=src, bem=bem_sol, meg=False, eeg=True, n_jobs=1) # mindist=5.0,\n\t\n\t13. save your bem, and fwd solutions\n\t\tbem_fname = pathlib.Path(data_path)/ 'E46_bem.fif'\n\t\tmne.bem.write_bem_solution(bem_fname, bem_sol, overwrite = True)\n\t\tfwd_fname = pathlib.Path(data_path)/'E46_fwd_soln.fif'\n\t\tmne.write_forward_solution(fwd_fname, fwd, overwrite=True)\n\n\t14. Create inverse operator (optional variables: loose=?, depth=?)\n\t\tinv = mne.minimum_norm.make_inverse_operator(info, fwd, noise_cov)\n\t\t\t- Loose = the spread of the signal across the brain (horizantal neurons --\u003e not pyramidal)\n\t\t\t- depth (only signif. if for not eloreta)\n\n\t15. determine SNR so you can set LAMBDA when applying inverse\n\t\tmne.viz.plot_snr_estimate(reconst_evoked, inv)\n\t\tsnr, snr_est = estimate_snr(reconst_evoked,inv)\n\n\t16. Now apply the inverse operator to gain your Inverse Solution, (recommended method = 'sLORETA' or 'eLORETA')\n\t\t*NOTE*\n\t\t\t- set lambda = 1/SNR^2\n\t\tstc = mne.minimum_norm.apply_inverse(reconst_evoked, inv, method = 'eLORETA', lambda2 = 0.1111111111111111111111111111111)\n\t\ta. if you loaded in your reconst_evoked\n\t\t\tstc = mne.minimum_norm.apply_inverse(reconst_evoked[0], inv, method = 'eLORETA')\n\n\t\n\t17. plotting source space EEG SNR overtime\n\t\tsnr_stc = stc.estimate_snr(reconst_evoked.info, fwd, noise_cov)\n\t\tsnr_stc.plot(hemi = 'both',smoothing_steps = 5, surface = 'pial')\n\t\t------\n\t\t\n\t\tsnr_stc = stc.estimate_snr(reconst_evoked[0].info, fwd, noise_cov)\n\t\tave = np.mean(snr_stc.data, axis=0)\n\n\t\tplt.pyplot.figure()\n\t\tplt.pyplot.plot(reconst_evoked.times, ave)\n\t\t#ax.plot(reconst_evoked[0].times, ave)\n\t\t#ax.set(xlabel='Time (sec)', ylabel='SNR MEG-EEG')\n\t\t#fig.tight_layout()\n\nPlotting:\n\t1. Plot the inverse solution\n\t\tbrain = stc.plot()\n\t2. Use this variable to fine tune your plots\n\t\tsurface_kwargs = dict(hemi = 'both', surface='inflated', subjects_dir = SUBJECTS_DIR, clim=dict(kind='value', lims=[3.5e-11, 6e-11, 8e-11]), views='lateral', initial_time=0.19, time_unit='s', size=(800,800), smoothing_steps=5)\n\t\t\t'surface' --\u003e determines what parts of the brain will be viewed ('white', 'pial', 'inflated')\n\t\t\t'lims' --\u003e  dictionary of bounds of amplitude activation\n\t\t\t'hemi' --\u003e which hemisphere are you viewing\n\n\t3. replot\n\t\tbrain = stc.plot(**surface_kwargs)\n\t\tstc.plot(hemi = 'split',smoothing_steps = 5, surface = 'pial')  # hemi = 'both'\n\t4. save\n\t\tcd *insert subject file name*\n\t\tstc.save('base_stc')\n\t\tcd ..\n\n\t\n\n--------------------- NEW SOL - Fsaverage MORPH -------------------\n\n1. Load in the src, stc and fsa_src\n\t#current_src = mne.read_source_spaces('/mnt/d/Aidan/Patient_src/' + subj + '-src.fif')\n\tfsa_src = mne.read_source_spaces(SUBJECTS_DIR + '/fsaverage/bem/fsaverage-ico-5-src.fif')\n\t#stc_path ='/mnt/d/Aidan/' + subj + '/base_stc-lh.stc'\n\t#stc_current = mne.source_estimate.read_source_estimate(stc_path)\n\n2. Morph the stc to fsa space\n\t#indepth\t- stc_morph_fsa = mne.compute_source_morph(current_src, subject_from=subj, subject_to='fsaverage', subjects_dir=SUBJECTS_DIR, zooms='auto', niter_affine=(100, 100, 10), niter_sdr=(5, 5, 3), spacing=5, smooth=None, warn=True, xhemi=False, sparse=False, src_to=fsa_src, precompute=False, verbose=False)\n\t#fwdsoln\t- stc_morph_fsa = mne.compute_source_morph(current_src, subject_from=subj, subject_to='fsaverage', subjects_dir=SUBJECTS_DIR, src_to=fwd[fsa_src])\n\t#best\t\t- stc_morph_fsa = mne.compute_source_morph(src, subject_from=subj, subject_to='fsaverage', subjects_dir=SUBJECTS_DIR, src_to=fsa_src)\n\n3. apply the stc  \n\tstc_final = stc_morph_fsa.apply(stc) #stc_current\n\n4. plot the morphed stcf\n\tstc_final.plot(hemi = 'split',smoothing_steps = 5, surface = 'pial')\n\n5. Save the morphed STC\n\tcd Grand_averages\n\tcd Source_estimates\n\tstc_final.save(subj+ '_stc')\n\n\n--- If you decide to read in data individually, re-do the pipeline ---\n- read bem solution\n\tbem_sol = mne.read_bem_solution('/mnt/d/Aidan/' + subj+ '/Digitization/' + subj+ '_bem.fif')\n- read reconst_evoked\n\treconst_evoked = mne.read_evoked\n\tinfo = reconst_evoked.info\n- read trans\n\ttrans = mne.read_trans('/mnt/d/Aidan/' + patient + '/Digitization/' + subj+ '-trans.fif')\n\nfwd_morph = mne.make_forward_solution(info, trans=trans, src=src_morph_fsa, bem=bem_sol, meg=False, eeg=True, mindist=5.0, n_jobs=1)\ninv_morph = mne.minimum_norm.make_inverse_operator(info, fwd_morph, noise_cov)\nstc_morph = mne.minimum_norm.apply_inverse(reconst_evoked, inv_morph, method = 'eLORETA')\n\n\n## -- getting the ISI and jitter ----\n\ntime_events = mne.events_from_annotations(raw)\ndif = 0\nmax_dif = 0\nmin_dif = 0\ndif_total = 0\nholder = 0\nprev = 0\naverage_dif = 0\ncurrent = 0\nfor i in range (1,201):\n    if (time_events[0])[i][2] \u003c 3:\n        if prev == 0:\n            prev = time_events[0][i][0]\n            holder = 1\n        elif i == 200:\n            current = time_events[0][i][0]\n            dif = current-prev\n            dif_total = dif + dif_total\n            average_dif = dif_total/i        \n        elif holder == 1:\n            if dif == 0:\n                current = time_events[0][i][0]\n                dif = current-prev\n                dif_total = dif + dif_total\n                max_dif = dif\n                min_dif = dif\n                prev = current\n                print('banana')\n            else:\n                current = time_events[0][i][0]\n                dif = current-prev\n                dif_total = dif + dif_total\n                prev = current\n                if dif \u003e max_dif:\n                    if dif \u003e max_dif*2:\n                        print(i)\n                    else:\n                        max_dif = dif\n                elif dif \u003c min_dif:\n                    min_dif = dif\nprint(max_dif)\nprint(min_dif)\nprint(average_dif)\n            ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoganlab%2Ftwo_beep_eeg_sourcelocalization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoganlab%2Ftwo_beep_eeg_sourcelocalization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoganlab%2Ftwo_beep_eeg_sourcelocalization/lists"}