using NeuroAnalyzer
using Plots
= load("files/eeg.hdf"); eeg
[ Info: Loaded: EEG (24 × 308480 × 1; 1204.996 s)
Load data:
using NeuroAnalyzer
using Plots
= load("files/eeg.hdf"); eeg
[ Info: Loaded: EEG (24 × 308480 × 1; 1204.996 s)
Electrode pops: these are gradual change of the amplitude, than rapid changes of amplitude, followed by gradual change of the amplitude. Here are examples of two pops:
Remove pops:
remove_pops!(eeg) # all channels
remove_pops!(eeg, ch=3, repair=false) # do not repair, just detect
remove_pops!(eeg, window=2.0) # use 2-second window
remove_pops!(eeg, r=10) # use 10-sample detection segments
(!) remove_pops()
and remove_pops!()
must be applied to a continuous (non-epoched signal).
(!) It is recommended do demean (remove_dc()
) the signal prior to removing pops.
The same segment after removal:
remove_pops()
and remove_pops!()
return the list of detected pops:
Detect and remove pops:
remove_dc!(eeg, ch="all")
= remove_pops(eeg, ch="eeg") eeg_new, pl, ls, rs
(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 => "", :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 … 1204.961, 1204.965, 1204.969, 1204.973, 1204.977, 1204.98, 1204.984, 1204.988, 1204.992, 1204.996], [0.0, 0.004, 0.008, 0.012, 0.016, 0.02, 0.023, 0.027, 0.031, 0.035 … 1204.961, 1204.965, 1204.969, 1204.973, 1204.977, 1204.98, 1204.984, 1204.988, 1204.992, 1204.996], [-0.025403620098183935 98.54673012251955 … -3.2714957911527685 -0.08773967535113832; 0.1593373391798476 -53.78607164784317 … 2.7328424966557443 0.04319671750270016; … ; -0.0662224732438267 126.99329299856757 … -0.6825976929190883 -0.04321418078028806; -0.31502003215746616 529.740937449184 … -9.067568486230204 -0.25761035026718876;;;], 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)", "remove_dc(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], n=0)", "reset_components(OBJ)", "remove_pops(OBJ, ch=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21], repair=true, window=2560.0)"]), [[1, 3518], [1, 19882], [1, 22214], [1, 25888], [1, 29590], [1, 38838], [1, 41794], [1, 47701], [1, 49340], [1, 56646] … [21, 223513], [21, 228418], [21, 239297], [21, 277179], [21, 283696], [21, 286395], [21, 294086], [21, 295033], [21, 300814], [21, 306270]], [6, 6, 13, 10, 9, 6, 9, 9, 6, 18 … 7, 9, 11, 14, 5, 8, 9, 6, 5, 9], [8, 240, 54, 10, 6, 652, 5, 6, 7, 7 … 5, 6, 5, 5, 7, 5, 5, 8, 45, 6])
pl
contains the list of pop locations: [channel, sample number]. ls
and rs
are the list of segments lengths before and after the pop that start at zero-crossing. Repairs are done within these segments. Using these segments we may visualize the pop:
Before:
1][1] # channel
pl[1][2] # pop locations
pl[= eeg.data[pl[1][1], (pl[1][2] - 100):(pl[1][2] + 100), 1]
s = Plots.plot(s, legend=false)
p vline!([100], ls=:dot)
Plots.plot!([100, (100 - ls[1])], [0, 0], lc=:black)
Plots.plot!([100, (100 + rs[1])], [0, 0], lc=:black) Plots.
After removal:
= eeg_new.data[pl[1][1], (pl[1][2] - 100):(pl[1][2] + 100), 1]
s = Plots.plot(s, legend=false)
p vline!([100], ls=:dot)
Plots.plot!([100, (100 - ls[1])], [0, 0], lc=:black)
Plots.plot!([100, (100 + rs[1])], [0, 0], lc=:black) Plots.