|
54 | 54 | # Mark known bad channels |
55 | 55 | raw.info["bads"] = ["MEG1933", "MEG2421"] |
56 | 56 |
|
57 | | -# The first 32 events correspond to dipole activations. |
| 57 | +# The first 32 events correspond to dipole activations |
58 | 58 | events = find_events(raw, "STI201") |
59 | 59 |
|
60 | 60 |
|
|
71 | 71 | raw, events, event_id, tmin, tmax, baseline=(None, bmax), preload=False |
72 | 72 | ) |
73 | 73 |
|
74 | | -# We drop the first and last event, it can contains dipole-switching artifacts |
| 74 | +# We drop the first and last event, it can contain dipole-switching artifacts |
75 | 75 | epochs_clean = epochs[1:-1] |
76 | 76 |
|
77 | 77 | # We select the first simulated dipole for visualisation purposes |
78 | 78 | epochs_firstdip = epochs_clean["1"] |
79 | 79 |
|
80 | 80 | # %% |
81 | | -# Let's look at the evoked response for the first clean dipole |
82 | | -# We can see that the phantom was set to produce 20 Hz sinusoidal bursts of current. |
| 81 | +# Let's look at the evoked response for the first clean dipole. |
| 82 | +# |
| 83 | +# We can see that the phantom was set to produce 20 Hz sinusoidal bursts of current |
83 | 84 | # and the burst envelope repeats at approximately 3 Hz. |
84 | 85 |
|
85 | 86 | epochs_firstdip.average().plot(time_unit="s") |
|
92 | 93 |
|
93 | 94 | # Get the evoked signal of the first dipole |
94 | 95 | evoked_tmp = epochs_firstdip.average() |
| 96 | + |
95 | 97 | # Calculate GFP |
96 | 98 | gfp = np.std(evoked_tmp.data, axis=0) |
97 | 99 |
|
|
116 | 118 | evoked = mne.EvokedArray(np.array(evoked.data), evoked.info, tmin=0.0) |
117 | 119 | evokeds.append(evoked) |
118 | 120 | # %% |
119 | | -# Next, we need to compute the noise covariance to capture the sensor noise structure. |
120 | | -# We use the baseline window to estimate covariance. |
121 | | -# You can explore the covariance tutorial for details: :ref:`tut-compute-covariance`. |
| 121 | +# Next, we need to compute the noise covariance in the baseline window |
| 122 | +# to capture the sensor noise structure (for details: :ref:`tut-compute-covariance`). |
122 | 123 |
|
123 | 124 | cov = mne.compute_covariance(epochs_clean, tmax=bmax) |
124 | 125 | del epochs # delete to save memory |
125 | 126 | # %% |
126 | | -# %% |
127 | 127 | # We use a :ref:`sphere head geometry model <eeg_sphere_model>` |
128 | 128 | # because the Elekta phantom is designed to approximate a spherical |
129 | 129 | # conductor with known dipole locations. |
|
146 | 146 | # Evaluate goodness of fit |
147 | 147 | # ------------------------ |
148 | 148 | # The dipole object stores the goodness of fit (GOF) for each dipole. |
149 | | -# Some dipoles have lower GOF because... |
| 149 | +# Some dipoles have a low GOF (< 60 %). |
150 | 150 | gof = [dip.gof[0] for dip in dip_all] |
151 | 151 | colors = ["#E69F00" if val < 60 else "#0072B2" for val in gof] |
152 | 152 | plt.bar(event_id, gof, color=colors) |
|
157 | 157 | # %% |
158 | 158 | # Dipoles with low goodness of fit |
159 | 159 | # -------------------------------- |
160 | | -# Why do some dipoles have a low (<60) GOF? |
161 | | -# Here we plot the dipole locations of the dipoles with low GOF. |
162 | | -# The dipoles with low GOF are deep in the brain which might explain |
| 160 | +# Why do some dipoles have a low GOF? |
| 161 | +# Here we plot the dipole locations of the dipoles with low GOF |
| 162 | +# We can see that dipoles with low GOF are deep in the brain which might explain |
163 | 163 | # the low GOF. |
164 | 164 |
|
165 | 165 | # Get indices of low GOF dipoles |
|
174 | 174 | subject = "phantom_otaniemi" |
175 | 175 | trans = mne.transforms.Transform("head", "mri", np.eye(4)) |
176 | 176 |
|
| 177 | +# Plot the position and the orientation of the dipoles with low GOF |
177 | 178 | fig = mne.viz.plot_alignment( |
178 | 179 | evoked.info, |
179 | 180 | trans, |
|
186 | 187 | subjects_dir=subjects_dir, |
187 | 188 | ) |
188 | 189 |
|
189 | | -# Plot the position and the orientation of the dipoles with low GOF |
190 | 190 | fig = mne.viz.plot_dipole_locations( |
191 | 191 | dipoles=low_dips, mode="arrow", subject=subject, color=(1.0, 0.2, 0.2), fig=fig |
192 | 192 | ) |
193 | 193 | # %% |
194 | 194 | # Compare estimated and true dipoles |
195 | 195 | # ---------------------------------- |
196 | 196 | # The dipole fits closely match the true phantom data, |
197 | | -# achieving sub-centimeter accuracy (mean position error 2.7mm). |
| 197 | +# achieving sub-centimeter accuracy (mean position error 2.4mm). |
198 | 198 |
|
199 | 199 | # We get the true dipole positions from the phantoms |
200 | 200 | actual_pos, actual_ori = mne.dipole.get_phantom_dipoles() |
|
0 commit comments