Skip to content

Commit 111066e

Browse files
committed
final formatting
1 parent e27ac56 commit 111066e

1 file changed

Lines changed: 13 additions & 22 deletions

File tree

tutorials/inverse/80_brainstorm_phantom_elekta.py

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@
4343
# -------------------------
4444

4545
# The data were collected with an Elekta Neuromag VectorView system
46-
# at 1000 Hz and low-pass filtered at 330 Hz.
47-
#
48-
# The dataset contains recordings at three current amplitudes (20, 200, and 2000 nAm).
46+
# at 1000 Hz, low-pass filtered at 330 Hz and contains recordings
47+
# at three current amplitudes (20, 200, and 2000 nAm).
4948
# Here we load the medium-amplitude condition.
5049
data_path = bst_phantom_elekta.data_path(verbose=True)
5150
raw_fname = data_path / "kojak_all_200nAm_pp_no_chpi_no_ms_raw.fif"
@@ -55,14 +54,13 @@
5554
raw.info["bads"] = ["MEG1933", "MEG2421"]
5655

5756
events = find_events(raw, "STI201")
58-
5957
# The first 32 events correspond to dipole activations.
6058

6159
# %%
6260
# Epoch the data and plot evokeds
6361
# -------------------------------
6462
#
65-
# We epoch the data around dipole events and apply baseline correction.
63+
# We epoch and baseline correct the data around the dipole events.
6664

6765
bmax = -0.05
6866
tmin, tmax = -0.1, 0.8
@@ -72,11 +70,11 @@
7270
raw, events, event_id, tmin, tmax, baseline=(None, bmax), preload=False
7371
)
7472

75-
# Plot evoked response for the first clean dipole
73+
# Here we plot the evoked response for the first clean dipole
7674
epochs["1"][1:-1].average().plot(time_unit="s")
7775
# %%
7876
# In this data the phantom was set to produce 20 Hz sinusoidal bursts of current.
79-
# You can see that the burst envelope repeats at approximately 3 Hz.
77+
# The burst envelope repeats at approximately 3 Hz.
8078
#
8179
# Determine peak activation using Global Field Power (GFP)
8280
# --------------------------------------------------------
@@ -86,34 +84,27 @@
8684
evoked_tmp = epochs["1"][1:-1].average()
8785
gfp = np.std(evoked_tmp.data, axis=0)
8886
times = evoked_tmp.times
89-
9087
# Restrict to first burst window
9188
time_mask = (times > 0) & (times <= 0.1)
92-
9389
peaks, _ = find_peaks(gfp[time_mask])
9490
peak_indices = np.where(time_mask)[0][peaks]
95-
9691
# Select the strongest peak
9792
strongest_peak_idx = peak_indices[np.argmax(gfp[peak_indices])]
9893
t_peak = times[strongest_peak_idx]
99-
10094
print(f"Strongest peak at {t_peak * 1000:.1f} ms")
10195
# %%
102-
# Here we store the evoked data for each dipole at the peak amplitude.
96+
# Here we crop the data at the peak amplitude and store the evoked data for each dipole.
10397
evokeds = []
10498
for ii in event_id:
10599
evoked = epochs[str(ii)][1:-1].average().crop(t_peak, t_peak)
106100
evoked = mne.EvokedArray(np.array(evoked.data), evoked.info, tmin=0.0)
107101
evokeds.append(evoked)
108102
# %%
109103
# Next, we need to compute the noise covariance to capture the sensor noise structure.
110-
#
111104
# We use the baseline window to estimate covariance.
112-
#
113105
# You can explore the covariance tutorial for details: :ref:`tut-compute-covariance`.
114106

115107
cov = mne.compute_covariance(epochs, tmax=bmax)
116-
117108
del epochs # delete to save memory
118109
# %%
119110
# We use a :ref:`sphere head geometry model <eeg_sphere_model>`
@@ -123,16 +114,15 @@
123114
sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=0.08)
124115

125116
# %%
126-
# Fit dipoles
117+
# Dipole fitting
127118
# -----------
128119

129-
# We fit dipoles for each phantom and store them in a list.
130-
dip_all, residuals_all = [], []
120+
# Finally, we fit dipoles for each phantom and store them in a list.
121+
dip_all = []
131122

132123
for evoked in evokeds:
133124
dip, residual = fit_dipole(evoked, cov, sphere, n_jobs=1)
134125
dip_all.append(dip)
135-
residuals_all.append(residual)
136126
# %%
137127
# Evaluate goodness of fit
138128
# ------------------------
@@ -144,13 +134,14 @@
144134
plt.xlabel("Phantom dipole estimation")
145135
plt.ylabel("Goodness of fit (%)")
146136
plt.show()
147-
137+
#
148138
# %%
149-
# We can see that GOF varies between 50 % and up to 95 %.
139+
# We can see that GOF varies between simulated dipoles from 50 % up to 95 %.
150140
#
151141
# Compare estimated and true dipoles
152142
# ----------------------------------
153143

144+
# We get the true dipole positions from the phantoms
154145
actual_pos, actual_ori = mne.dipole.get_phantom_dipoles()
155146
actual_amp = 200.0 # nAm
156147

@@ -189,7 +180,7 @@
189180
# The dipole fits closely match the true phantom data,
190181
# achieving sub-centimeter accuracy (mean position error 2.7mm).
191182
#
192-
# Visualise estimated and true dipoles
183+
# Visualise estimated and true dipole fits
193184
# ------------------------------------
194185

195186
actual_amp = np.ones(len(dip)) # fake amp, needed to create Dipole instance

0 commit comments

Comments
 (0)