You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: exercises_text/ni2_inverse5_scanning.md
+55-42
Original file line number
Diff line number
Diff line change
@@ -107,7 +107,7 @@ Up until now we have explored the covariance between two variables represented a
107
107
108
108
Let’s go back now to our basic observation model: `X = L*S+n`. If we now change this equation to include the individual contributions of the single sources, and forget about the noise we get:
109
109
110
-
X = l1*s1 + l2*s2 + … + ln*sn;
110
+
X = l1*s1 + l2*s2 + … + ln*sn
111
111
112
112
When we compute `X*X'` and observe the individual terms in `X` we are essentially doing the following:
113
113
@@ -118,14 +118,14 @@ There is a basic rule in matrix algebra that states that `(A*B)'` is the same as
Now the above equation looks complicated, but if we realize that `si*sj'` represents the covariance (or auto-covariance) between the sources `i` and `j`, and that these are scalar values (which means that it does not matter in which order you multiply this in a matrix multiplication), we can rewrite the above equation as:
The terms `li*lj'` are also called vector outer-products, so in words the above equation means that the covariance matrix can be represented as a _weighted sum_ of the leadfield outer products between all _pairs of sources_, where the weights are based on the covariance between the corresponding pairs of sources.
131
131
@@ -176,18 +176,18 @@ The filter output is defined as: `w'*X`
176
176
177
177
Let us now create some simulated data to demonstrate the beamformer.
@@ -221,28 +221,35 @@ Now we also compute the inverse of the covariance matrix, because it will be use
221
221
222
222
> We can now compute the source time courses reconstructed with the beamformer. Do this and call the result `sbf`.
223
223
224
-
We can now inspect what the shape of the reconstructed source time course is at the locations at which activity was simulated. Note that if we don’t constrain the orientation of the sources (i.e., use a 3-column leadfield per location) we will get a 3-row spatial filter per location. In order to go from the original position-based indices of the grid points, we need to do the following:
224
+
We can now inspect what the shape of the reconstructed source time course is at the locations at which activity was simulated. Note that if we don’t constrain the orientation of the sources (i.e., use a 3-column leadfield per location) we will get a 3-row spatial filter per location. In order to go from the original 3D grid indices that cover a regular gfrid inside _and_ outside the head, we need to do the following:
225
225
226
-
sel = find(ismember(find(sourcemodel.inside), [1110 2342 2352 2674]));
227
-
sel = repmat((sel-1)*3, 1, 3)+repmat(1:3, numel(sel), 1);
226
+
index = 1:numel(sourcemodel.inside); % these are all source positions, including the ones outside the brain
227
+
index1110 = find(index(sourcemodel.inside)==1110) % find the index of source position 1110, only considering the ones inside the brain
228
+
index2342 = find(index(sourcemodel.inside)==2342)
229
+
index2352 = find(index(sourcemodel.inside)==2352)
230
+
index2674 = find(index(sourcemodel.inside)==2674)
231
+
sel1110 = (index1110-1)*3 + (1:3) % find the three columns corresponding to source position 1110
232
+
sel2342 = (index2342-1)*3 + (1:3)
233
+
sel2352 = (index2352-1)*3 + (1:3)
234
+
sel2674 = (index2674-1)*3 + (1:3)
228
235
229
-
Each row in the matrix `sel` is a triplet of consecutive numbers that points to rows in the matrix of `wbf` (and `sbf`) that we are going to explore first.
236
+
Each vector `selXXX` is a triplet of consecutive numbers that points to rows in the matrix of `wbf` (and `sbf`) that we are going to explore first.
230
237
231
-
figure;
232
-
subplot(1, 2, 1); plot(t1, sbf(sel(1,:),:));
233
-
subplot(1, 2, 2); plot(t1, s4);
238
+
figure
239
+
subplot(1, 2, 1); plot(t, sbf(sel1110,:));
240
+
subplot(1, 2, 2); plot(t, s1);
234
241
235
-
figure;
236
-
subplot(1, 2, 1); plot(t1, sbf(sel(2,:),:));
237
-
subplot(1, 2, 2); plot(t1, s2);
242
+
figure
243
+
subplot(1, 2, 1); plot(t, sbf(sel2342,:));
244
+
subplot(1, 2, 2); plot(t, s2);
238
245
239
-
figure;
240
-
subplot(1, 2, 1); plot(t1, sbf(sel(3,:),:));
241
-
subplot(1, 2, 2); plot(t1, s1);
246
+
figure
247
+
subplot(1, 2, 1); plot(t, sbf(sel2352,:));
248
+
subplot(1, 2, 2); plot(t, s3);
242
249
243
-
figure;
244
-
subplot(1, 2, 1); plot(t1, sbf(sel(4,:),:));
245
-
subplot(1, 2, 2); plot(t1, s3);
250
+
figure
251
+
subplot(1, 2, 1); plot(t, sbf(sel2674,:));
252
+
subplot(1, 2, 2); plot(t, s4);
246
253
247
254
As you may have noticed, the resulting time courses are a bit noisy. This is due to the noise in the data being projected onto the estimated source time courses. This can be accounted for by a mathematical trick that is called regularization. This boils down to adding a scaled identity matrix to the sensor covariance matrix prior to calculating the inverse. This makes the mathematical inversion of the covariance matrix less sensitive to. The regularized inverse of the covariance matrix can be computed as:
248
255
@@ -269,20 +276,24 @@ To illustrate this depth bias, we first restructure the source-reconstructed sim
269
276
In order to represent the reconstruction as an image, we need to express the variance of the sources at each of the locations in a single number. Recall that at each location of the 3-dimensional grid the source activity consists of three time courses, one for each 'cardinal’ x/y/z orientation. A common way to achieve this is to sum the variance across the three orientations. This is essentially the application of Pythagoras’ rule (without explicitly taking the square and the square root, since variance is already a 'squared’ value). With our sbf variable it is possible to do this in the following way. Note that this variable is a 'number of inside sources x 3’ times 'number of timepoints’ matrix. If we compute the variance across time (`var(sbf, [], 2)`) we end up with a vector, that in consecutive triplets contains the variance in the x/y/z orientation at the 'inside’ dipole locations of the sourcemodel. We can now efficiently create the variance for each location by using MATLAB’s reshape and sum functions:
270
277
271
278
pbf = var(sbf, [], 2);
272
-
pbf = sum(reshape(pbf, 3, numel(pbf)/3));
279
+
pbf = reshape(pbf, 3, numel(pbf)/3);
280
+
pbf = sum(pbf, 1);
273
281
274
-
Take a moment to try and understand what is going on in the second line.
282
+
Take a moment to try and understand what is going on in the second and third line.
275
283
276
284
Now, create a FieldTrip type 'source’-structure, and use ft_sourceplot to visualize this.
@@ -302,7 +313,7 @@ In the previous section we have seen that the depth bias is related to the fact
302
313
303
314
We will use the variables `sensordata`, `sourcemodel` and `L` that we also used in section 3. We also need the leadfields and source timecourses that we used for the simulations. If you don’t have these variables anymore in MATLAB memory, you should re-create them.
304
315
305
-
Now we will simulate data from a 'second’ condition (compared to the original variable sensordata), where the sources have the exact same locations and time courses, but the amplitude of two sources is decreased, and the amplitude of the other sources is increased, relative to the 'first’ condition.
316
+
Now we will simulate data from a 'second’ condition (compared to the original variable sensordata), where the sources have the exact same locations and time courses, but the amplitude of two sources is decreased, and the amplitude of the two other sources is increased, relative to the 'first’ condition.
306
317
307
318
sensordata2 = 1.25 .* leadfield1*s1 + ...
308
319
0.80 .* leadfield2*s2 + ...
@@ -317,14 +328,16 @@ We will now compute the spatial filters using the covariance estimated from the
317
328
318
329
> Use the `iCr2` variable to compute the spatial filters in the same way as in section 3.2. Call this variable `wbfr2`. Then, compute the source time courses for the conditions separately (hint: use `wbfr2*sensordata` and `wbfr2*sensordata2`), and compute the condition specific power estimate (as in section 4.1). Calle these estimates `pbfr1` and `pbfr2`.
319
330
320
-
We can now create a FieldTrip style source-structure, and store in the field `avg.pow` a measure of the difference between condition 1 and 2.
331
+
We can now create a FieldTrip style source-structure, and store in the field `pow` a measure of the difference between condition 1 and 2.
0 commit comments