Using planar interpolation

NeuroAnalyzer tutorials: Process EEG (6)

Load data:

using NeuroAnalyzer
eeg = load("files/eeg.hdf");
e10 = epoch(eeg, ep_len=10)
[ Info: Loaded: EEG (24 × 308480 × 1; 1204.996 s)
NeuroAnalyzer.NEURO(NeuroAnalyzer.HEADER(Dict{Symbol, Any}(:weight => -1, :id => "", :middle_name => "", :height => -1, :head_circumference => -1, :handedness => "", :last_name => "528004  SIT 52, 20220831-122227-{d589f756-53fc-4f1b-915d-6e3b8c1560ad}", :first_name => ""), Dict{Symbol, Any}(:epoch_id => "length_10s", :channel_type => ["eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg"  …  "eeg", "eeg", "ref", "ref", "eeg", "eeg", "eeg", "eog", "eog", "ecg"], :label => ["Fp1", "Fp2", "F3", "F4", "C3", "C4", "P3", "P4", "O1", "O2"  …  "T5", "T6", "A1", "A2", "Fz", "Cz", "Pz", "EOG1", "EOG2", "ECG"], :prefiltering => ["HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz"  …  "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz"], :gain => [0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218  …  0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218], :data_type => "eeg", :recording_notes => "", :recording_date => "31.08.22", :sampling_rate => 256, :file_type => "EDF"…), Dict(:name => "", :design => "", :notes => "")), [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.023, 0.027, 0.031, 0.035  …  1199.961, 1199.965, 1199.969, 1199.973, 1199.977, 1199.98, 1199.984, 1199.988, 1199.992, 1199.996], [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.023, 0.027, 0.031, 0.035  …  9.961, 9.965, 9.969, 9.973, 9.977, 9.98, 9.984, 9.988, 9.992, 9.996], [0.06299352498755795 98.63512726760528 … 41.64779361459051 40.27715442572031; 0.11655563660927726 -53.828853350413745 … 345.96748535110487 347.7616741828556; … ; -0.022184604323419066 127.03733086748798 … 42.55039163342602 44.143978691184884; -0.055585528301492104 530.00037195304 … -179.54843878264597 -97.67507694089335;;; 40.58017280035072 38.69000241338162 … -7.037891014697759 -7.6384338583029905; 344.18870568332585 339.2435612554108 … -2.1636004350702924 -1.243066521339322; … ; 48.60829031932775 41.434311602707794 … 0.22361559170736633 5.107585048673709; -61.66159371531367 -60.51281779857858 … -25.091166799203215 -12.149362788293596;;; -7.389384663780996 -7.618556612450722 … 1.3595844397118169 0.89911474206312; -3.5767735100748306 -0.30843418447498117 … 2.5866028445011846 -0.5132850019084954; … ; 1.3968065710167448 4.064826278034884 … 20.59119020676338 15.167853967159978; -27.014555021283574 -12.020921093458888 … 13.363788037149643 4.117227772690271;;; … ;;; 18.569309294713733 22.89311361283536 … 4.754504204065761 1.2053936473657352; 4.494714018514111 13.02609030059181 … 5.464449674126968 -2.6002896761179723; … ; -0.20841131938738222 12.507075249278618 … -7.241776899887379 -16.6315533872683; -29.255972440543367 -19.25691477874347 … 51.4201275519938 43.947841516236736;;; -1.4299687612461471 -1.312451759360422 … -0.5864522963548433 -6.796427233556682; 0.012850100616558002 0.570051044210814 … 4.181275800561462 -2.4365803124421292; … ; -6.719338934443345 -5.029725597318926 … 3.433495081847715 -3.6700683194834482; 56.10007507089348 40.45064953005437 … 7.692870188391213 -0.9038428781168477;;; -5.560172661791544 -0.11512766557237253 … 19.084481856614218 16.407156218345452; 5.141449021164782 -3.3199724764366856 … 3.3810434974559325 3.5815380669519286; … ; 3.114487125536476 -6.350212297090032 … 9.640660281430884 10.73198290953739; 9.746916484991555 3.5775514229256995 … -21.665073186614904 -26.318948530205475], Dict{Any, Any}(), 0×5 DataFrame
 Row  id      start    length   description  channel  String  Float64  Float64  String       Int64   
─────┴────────────────────────────────────────────────, 23×9 DataFrame
 Row  label   loc_radius  loc_theta  loc_x    loc_y    loc_z    loc_radius_sp ⋯
     │ String  Float64     Float64    Float64  Float64  Float64  Float64       ⋯
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ Fp1           1.0       108.0    -0.31     0.95    -0.03            1.0 ⋯
   2 │ Fp2           1.0        72.0     0.31     0.95    -0.03            1.0
   3 │ F7            1.0       144.0    -0.81     0.59    -0.03            1.0
   4 │ F3            0.65      129.0    -0.55     0.67     0.5             1.0
   5 │ Fz            0.51       90.0     0.0      0.72     0.7             1.0 ⋯
   6 │ F4            0.65       51.0     0.55     0.67     0.5             1.0
   7 │ F8            1.0        36.0     0.81     0.59    -0.03            1.0
   8 │ T3            1.0       180.0    -1.0      0.0     -0.03            1.0
   9 │ C3            0.51      180.0    -0.72     0.0      0.7             1.0 ⋯
  10 │ Cz            0.0         0.0     0.0      0.0      1.0             1.0
  11 │ C4            0.51        0.0     0.72     0.0      0.7             1.0
  ⋮  │   ⋮         ⋮           ⋮         ⋮        ⋮        ⋮           ⋮       ⋱
  14 │ P3            0.65      231.0    -0.55    -0.67     0.5             1.0
  15 │ Pz            0.51      270.0     0.0     -0.72     0.7             1.0 ⋯
  16 │ P4            0.65      309.0     0.55    -0.67     0.5             1.0
  17 │ T6            1.0       324.0     0.81    -0.59    -0.03            1.0
  18 │ O1            1.0       252.0    -0.31    -0.95    -0.03            1.0
  19 │ O2            1.0       288.0     0.31    -0.95    -0.03            1.0 ⋯
  20 │ A1            1.0       192.0    -0.92    -0.23    -0.55            1.1
  21 │ A2            1.0       -12.0     0.92    -0.23    -0.55            1.1
  22 │ EOG1          1.01      149.0    -0.87     0.51    -0.37            1.0
  23 │ EOG2          1.01       31.0     0.87     0.51    -0.37            1.0 ⋯
                                                    3 columns and 2 rows omitted, ["reset_components(OBJ)", "filter(OBJ, ch=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], fprototype=iirnotch, ftype=nothing, cutoff=50, order=8, rp=-1, rs=-1, dir=twopass, w=nothing)", "reset_components(OBJ)", "filter(OBJ, ch=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], fprototype=fir, ftype=hp, cutoff=0.1, order=8, rp=-1, rs=-1, dir=twopass, w=nothing)", "reset_components(OBJ)", "epoch(OBJ, marker=, offset=0, ep_n=nothing, ep_len=2560)"])

Interpolate bad channel Fp1, epoch 1:2 using planar interpolation:

e10pl = plinterpolate_channel(e10, ch="Fp1", ep=1:2)
Plots.plot(e10.data[1, :, 1])
Plots.plot!(e10pl.data[1, :, 1])
Progress:   0%|                    |  ETA: 5:31:34Progress:   2%|▍                   |  ETA: 0:08:25Progress:   3%|▋                   |  ETA: 0:06:14Progress:   4%|▊                   |  ETA: 0:05:08Progress:   5%|█                   |  ETA: 0:04:28Progress:   6%|█▏                  |  ETA: 0:04:01Progress:   7%|█▍                  |  ETA: 0:03:40Progress:   8%|█▌                  |  ETA: 0:03:25Progress:   9%|█▊                  |  ETA: 0:03:18Progress:  14%|██▉                 |  ETA: 0:02:32Progress:  15%|███                 |  ETA: 0:02:28Progress:  20%|████                |  ETA: 0:02:07Progress:  21%|████▏               |  ETA: 0:02:05Progress:  22%|████▍               |  ETA: 0:02:03Progress:  26%|█████▏              |  ETA: 0:01:50Progress:  27%|█████▍              |  ETA: 0:01:48Progress:  28%|█████▌              |  ETA: 0:01:46Progress:  28%|█████▊              |  ETA: 0:01:45Progress:  29%|█████▉              |  ETA: 0:01:43Progress:  31%|██████▎             |  ETA: 0:01:40Progress:  34%|██████▉             |  ETA: 0:01:33Progress:  35%|███████             |  ETA: 0:01:32Progress:  36%|███████▎            |  ETA: 0:01:30Progress:  37%|███████▍            |  ETA: 0:01:29Progress:  38%|███████▌            |  ETA: 0:01:27Progress:  40%|████████▏           |  ETA: 0:01:22Progress:  41%|████████▎           |  ETA: 0:01:21Progress:  44%|████████▊           |  ETA: 0:01:17Progress:  45%|█████████           |  ETA: 0:01:15Progress:  46%|█████████▏          |  ETA: 0:01:13Progress:  46%|█████████▎          |  ETA: 0:01:12Progress:  47%|█████████▌          |  ETA: 0:01:11Progress:  48%|█████████▋          |  ETA: 0:01:10Progress:  49%|█████████▊          |  ETA: 0:01:09Progress:  51%|██████████▎         |  ETA: 0:01:05Progress:  52%|██████████▌         |  ETA: 0:01:03Progress:  53%|██████████▋         |  ETA: 0:01:02Progress:  54%|██████████▊         |  ETA: 0:01:01Progress:  55%|███████████         |  ETA: 0:01:00Progress:  61%|████████████▎       |  ETA: 0:00:51Progress:  62%|████████████▍       |  ETA: 0:00:49Progress:  63%|████████████▋       |  ETA: 0:00:48Progress:  64%|████████████▊       |  ETA: 0:00:47Progress:  64%|████████████▉       |  ETA: 0:00:46Progress:  65%|█████████████       |  ETA: 0:00:45Progress:  70%|██████████████      |  ETA: 0:00:38Progress:  71%|██████████████▎     |  ETA: 0:00:37Progress:  72%|██████████████▍     |  ETA: 0:00:36Progress:  73%|██████████████▌     |  ETA: 0:00:35Progress:  74%|██████████████▊     |  ETA: 0:00:34Progress:  78%|███████████████▌    |  ETA: 0:00:29Progress:  78%|███████████████▊    |  ETA: 0:00:28Progress:  79%|███████████████▉    |  ETA: 0:00:27Progress:  82%|████████████████▍   |  ETA: 0:00:23Progress:  83%|████████████████▌   |  ETA: 0:00:22Progress:  84%|████████████████▊   |  ETA: 0:00:21Progress:  85%|████████████████▉   |  ETA: 0:00:20Progress:  85%|█████████████████   |  ETA: 0:00:19Progress:  86%|█████████████████▎  |  ETA: 0:00:18Progress:  87%|█████████████████▍  |  ETA: 0:00:17Progress:  90%|██████████████████  |  ETA: 0:00:12Progress:  91%|██████████████████▎ |  ETA: 0:00:11Progress:  92%|██████████████████▍ |  ETA: 0:00:10Progress:  93%|██████████████████▋ |  ETA: 0:00:09Progress:  94%|██████████████████▊ |  ETA: 0:00:08Progress:  94%|██████████████████▉ |  ETA: 0:00:07Progress:  95%|███████████████████ |  ETA: 0:00:06Progress:  97%|███████████████████▍|  ETA: 0:00:04Progress:  98%|███████████████████▌|  ETA: 0:00:03Progress:  99%|███████████████████▊|  ETA: 0:00:02Progress:  99%|███████████████████▉|  ETA: 0:00:01Progress: 100%|████████████████████| Time: 0:02:05

(!) Planar interpolation requires electrode locations. Only a single channel may be interpolated at the same time. Channel may be interpolated across more than 1 epoch.

(!) This experimental modeling is based on ScatteredInterpolation.interpolate() and requires further validations.

Using linear regression

Interpolate bad channel C3, epoch 25 using linear regression, use epochs 17:24 as reference:

e10lr = lrinterpolate_channel(e10, ch="C3", ep=25)
m[ Info: Accuracy report:
[ Info:  R²: 0.934
[ Info:  R² adj: 0.934
[ Info:  AIC: 1.489141688e6
[ Info:  BIC: 1.489328955e6
[ Info:  RMSE: 0.077
[ Info:  MAE: 9.307
NeuroAnalyzer.NEURO(NeuroAnalyzer.HEADER(Dict{Symbol, Any}(:weight => -1, :id => "", :middle_name => "", :height => -1, :head_circumference => -1, :handedness => "", :last_name => "528004  SIT 52, 20220831-122227-{d589f756-53fc-4f1b-915d-6e3b8c1560ad}", :first_name => ""), Dict{Symbol, Any}(:epoch_id => "length_10s", :channel_type => ["eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg", "eeg"  …  "eeg", "eeg", "ref", "ref", "eeg", "eeg", "eeg", "eog", "eog", "ecg"], :label => ["Fp1", "Fp2", "F3", "F4", "C3", "C4", "P3", "P4", "O1", "O2"  …  "T5", "T6", "A1", "A2", "Fz", "Cz", "Pz", "EOG1", "EOG2", "ECG"], :prefiltering => ["HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz"  …  "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz", "HP:0,18Hz LP:104,0Hz"], :gain => [0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218  …  0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218, 0.17935713740749218], :data_type => "eeg", :recording_notes => "", :recording_date => "31.08.22", :sampling_rate => 256, :file_type => "EDF"…), Dict(:name => "", :design => "", :notes => "")), [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.023, 0.027, 0.031, 0.035  …  1199.961, 1199.965, 1199.969, 1199.973, 1199.977, 1199.98, 1199.984, 1199.988, 1199.992, 1199.996], [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.023, 0.027, 0.031, 0.035  …  9.961, 9.965, 9.969, 9.973, 9.977, 9.98, 9.984, 9.988, 9.992, 9.996], [0.06299352498755795 98.63512726760528 … 41.64779361459051 40.27715442572031; 0.11655563660927726 -53.828853350413745 … 345.96748535110487 347.7616741828556; … ; -0.022184604323419066 127.03733086748798 … 42.55039163342602 44.143978691184884; -0.055585528301492104 530.00037195304 … -179.54843878264597 -97.67507694089335;;; 40.58017280035072 38.69000241338162 … -7.037891014697759 -7.6384338583029905; 344.18870568332585 339.2435612554108 … -2.1636004350702924 -1.243066521339322; … ; 48.60829031932775 41.434311602707794 … 0.22361559170736633 5.107585048673709; -61.66159371531367 -60.51281779857858 … -25.091166799203215 -12.149362788293596;;; -7.389384663780996 -7.618556612450722 … 1.3595844397118169 0.89911474206312; -3.5767735100748306 -0.30843418447498117 … 2.5866028445011846 -0.5132850019084954; … ; 1.3968065710167448 4.064826278034884 … 20.59119020676338 15.167853967159978; -27.014555021283574 -12.020921093458888 … 13.363788037149643 4.117227772690271;;; … ;;; 18.569309294713733 22.89311361283536 … 4.754504204065761 1.2053936473657352; 4.494714018514111 13.02609030059181 … 5.464449674126968 -2.6002896761179723; … ; -0.20841131938738222 12.507075249278618 … -7.241776899887379 -16.6315533872683; -29.255972440543367 -19.25691477874347 … 51.4201275519938 43.947841516236736;;; -1.4299687612461471 -1.312451759360422 … -0.5864522963548433 -6.796427233556682; 0.012850100616558002 0.570051044210814 … 4.181275800561462 -2.4365803124421292; … ; -6.719338934443345 -5.029725597318926 … 3.433495081847715 -3.6700683194834482; 56.10007507089348 40.45064953005437 … 7.692870188391213 -0.9038428781168477;;; -5.560172661791544 -0.11512766557237253 … 19.084481856614218 16.407156218345452; 5.141449021164782 -3.3199724764366856 … 3.3810434974559325 3.5815380669519286; … ; 3.114487125536476 -6.350212297090032 … 9.640660281430884 10.73198290953739; 9.746916484991555 3.5775514229256995 … -21.665073186614904 -26.318948530205475], Dict{Any, Any}(), 0×5 DataFrame
 Row  id      start    length   description  channel  String  Float64  Float64  String       Int64   
─────┴────────────────────────────────────────────────, 23×9 DataFrame
 Row  label   loc_radius  loc_theta  loc_x    loc_y    loc_z    loc_radius_sp ⋯
     │ String  Float64     Float64    Float64  Float64  Float64  Float64       ⋯
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ Fp1           1.0       108.0    -0.31     0.95    -0.03            1.0 ⋯
   2 │ Fp2           1.0        72.0     0.31     0.95    -0.03            1.0
   3 │ F7            1.0       144.0    -0.81     0.59    -0.03            1.0
   4 │ F3            0.65      129.0    -0.55     0.67     0.5             1.0
   5 │ Fz            0.51       90.0     0.0      0.72     0.7             1.0 ⋯
   6 │ F4            0.65       51.0     0.55     0.67     0.5             1.0
   7 │ F8            1.0        36.0     0.81     0.59    -0.03            1.0
   8 │ T3            1.0       180.0    -1.0      0.0     -0.03            1.0
   9 │ C3            0.51      180.0    -0.72     0.0      0.7             1.0 ⋯
  10 │ Cz            0.0         0.0     0.0      0.0      1.0             1.0
  11 │ C4            0.51        0.0     0.72     0.0      0.7             1.0
  ⋮  │   ⋮         ⋮           ⋮         ⋮        ⋮        ⋮           ⋮       ⋱
  14 │ P3            0.65      231.0    -0.55    -0.67     0.5             1.0
  15 │ Pz            0.51      270.0     0.0     -0.72     0.7             1.0 ⋯
  16 │ P4            0.65      309.0     0.55    -0.67     0.5             1.0
  17 │ T6            1.0       324.0     0.81    -0.59    -0.03            1.0
  18 │ O1            1.0       252.0    -0.31    -0.95    -0.03            1.0
  19 │ O2            1.0       288.0     0.31    -0.95    -0.03            1.0 ⋯
  20 │ A1            1.0       192.0    -0.92    -0.23    -0.55            1.1
  21 │ A2            1.0       -12.0     0.92    -0.23    -0.55            1.1
  22 │ EOG1          1.01      149.0    -0.87     0.51    -0.37            1.0
  23 │ EOG2          1.01       31.0     0.87     0.51    -0.37            1.0 ⋯
                                                    3 columns and 2 rows omitted, ["reset_components(OBJ)", "filter(OBJ, ch=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], fprototype=iirnotch, ftype=nothing, cutoff=50, order=8, rp=-1, rs=-1, dir=twopass, w=nothing)", "reset_components(OBJ)", "filter(OBJ, ch=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], fprototype=fir, ftype=hp, cutoff=0.1, order=8, rp=-1, rs=-1, dir=twopass, w=nothing)", "reset_components(OBJ)", "epoch(OBJ, marker=, offset=0, ep_n=nothing, ep_len=2560)", "reset_components(OBJ)", "lrinterpolate_channel(OBJ, ch=5, ep=25, ep_ref=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120])"])

(!) This experimental modeling is based on GLM.lm() and requires further validations.

iview(e10, e10lr)