Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MRG: Fix the computation of the orientation in (..)MxNE and gamma-map #4633

Merged
merged 17 commits into from
Oct 12, 2017

Conversation

yousrabk
Copy link
Contributor

@yousrabk yousrabk commented Oct 2, 2017

No description provided.

for ii in range(len(active_src)):
for jj in range(3):
if in_pos >= len(active_set):
break
if (active_set[in_pos] + jj) % 3 == 0:
X_xyz[3 * ii + jj] = X[in_pos]
X_ori_[3 * ii + jj] = X_ori[in_pos]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XXX: There is still a problem here, I have to check what is happening when we give xyz_same_gamma=False

@yousrabk yousrabk changed the title Fix the computation of the orientation in (..)MxNE and gamma-map WIP: Fix the computation of the orientation in (..)MxNE and gamma-map Oct 2, 2017
@codecov-io
Copy link

codecov-io commented Oct 2, 2017

Codecov Report

Merging #4633 into master will decrease coverage by <.01%.
The diff coverage is 96.55%.

@@            Coverage Diff             @@
##           master    #4633      +/-   ##
==========================================
- Coverage   87.69%   87.68%   -0.01%     
==========================================
  Files         351      351              
  Lines       66554    66635      +81     
  Branches    10343    11554    +1211     
==========================================
+ Hits        58362    58429      +67     
- Misses       5233     5256      +23     
+ Partials     2959     2950       -9

@@ -277,8 +277,10 @@ def gamma_map(evoked, forward, noise_cov, alpha, loose="auto", depth=0.8,

# Reapply weights to have correct unit
n_dip_per_pos = 1 if is_fixed_orient(forward) else 3
X_ori = X.copy()
X = _reapply_source_weighting(X, source_weighting,
active_set, n_dip_per_pos)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n_dip_per_pos is not used in _reapply_source_weighting :(

X = _reapply_source_weighting(X, source_weighting,
active_set, n_dip_per_pos)
X_ori /= source_weighting[active_set][:, None]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks bogus. _reapply_source_weighting does `X *= source_weighting[active_set][:, None]``
so I doubt it's doing the right thing but it's just a guess


tmin = evoked.times[0]
tstep = 1.0 / evoked.info['sfreq']

if return_as_dipoles:
out = _make_dipoles_sparse(X, active_set, forward, tmin, tstep, M,
M_estimated, active_is_idx=True)
M_estimated, active_is_idx=True,
X_ori=X_ori)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's really a mystery to me why you need to pass both X and X_ori and why internally you use X to get amplitude and X_ori to get orientation.

@@ -124,5 +124,20 @@ def test_gamma_map_vol_sphere():

assert_array_almost_equal(stc.times, evoked.times, 5)

# Compare orientation obtained using fit_dipole and mixed_norm
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gamma_map

pos2 = src[0]['rr'][stc.vertices[1]]
evoked_dip = mne.simulation.simulate_evoked(fwd, stc, info, cov, nave=1e9)

dip_mxne = gamma_map(evoked_dip, fwd, cov, alpha, return_as_dipoles=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dip_gmap

@larsoner larsoner added this to the 0.15 milestone Oct 3, 2017
@@ -24,8 +24,7 @@
@verbose
def _prepare_weights(forward, gain, source_weighting, weights, weights_min):
mask = None
if isinstance(weights, SourceEstimate):
# weights = np.sqrt(np.sum(weights.data ** 2, axis=1))
if isinstance(weights, (SourceEstimate, VolSourceEstimate)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if isinstance(weights, _BaseSourceEstimate):


amp_max = [np.max(d.amplitude) for d in dip_mxne]
dip_mxne = dip_mxne[np.argmax(amp_max)]
assert_true(dip_mxne[0].pos[0] in pos)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not pass on master but the assert below on ori does.

so this test is not enough to demonstrate the bug fix on orientation
estimation.



def plot_pos_ori(pos, ori, color=(0., 0., 0.)):
mlab.points3d(pos[0], pos[1], pos[2], scale_factor=0.005,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this works if you pass pos of shape (3, n_times)

as is the example is broken

@@ -137,3 +138,19 @@

fig.tight_layout()
plt.show()


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh okay.

In any case, please make this a separate section with ########### so it renders nicer in SG

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

@agramfort
Copy link
Member

agramfort commented Oct 9, 2017 via email

@yousrabk
Copy link
Contributor Author

yousrabk commented Oct 9, 2017

Are we good here after Eric's comment?

@agramfort
Copy link
Member

agramfort commented Oct 9, 2017 via email

@agramfort agramfort changed the title WIP: Fix the computation of the orientation in (..)MxNE and gamma-map MRG: Fix the computation of the orientation in (..)MxNE and gamma-map Oct 10, 2017
@agramfort
Copy link
Member

ok I did I pass

@yousrabk have a look

FYI @joewalter we realized that the depth weighting strategy for sparse solver was not optimal for orientation estimation and we now use the Frobenius normalization you had written in the past.

Copy link
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM

@@ -53,7 +53,7 @@

###############################################################################
# Run solver
alpha = 50 # regularization parameter between 0 and 100 (100 is high)
alpha = 55 # regularization parameter between 0 and 100 (100 is high)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you made this change because the example now otherwise looks bad, we'll have to make it clear in the whats_new (please update) that the computations have changed and that changing alpha might be necessary to partially compensate.


dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0]
assert_true(np.max(np.abs(np.dot(dip_fit.ori[0],
dip_gmap.ori.T))) > 0.99)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a max here? Aren't these single dipoles? If so you can just do np.abs(np.dot(dip_fit.ori[0], dip_gmap.ori[0])).

Something else just occurred to me -- if we guarantee our dipoles have positive amplitude values during fitting, then the abs isn't even needed, because they should both point in the "outward" direction. But we can fix this bit later if you don't want to investigate (but please add an XXX comment so we don't forget)

assert_true(dip_gmap[0].pos[0] in src[0]['rr'][stc.vertices])

dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0]
assert_true(np.abs(np.dot(dip_fit.ori[0], dip_gmap.ori[0])) > 0.99) # XXX
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yousrabk why the XXX?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was in response to my request to add a # XXX comment to signify that we should look into whether the abs is even necessary at some point (if currents are always positive it shouldn't be), but without at least a few words saying this, it is tough to know that

@agramfort
Copy link
Member

agramfort commented Oct 11, 2017 via email

@larsoner
Copy link
Member

yes it is necessary since there is no reason why the sign of the amplitude of the dipoles should be fixed.

My point is that we could (for fit_dipole) choose to always select the orientation that gives a positive current. Then we wouldn't need it.

@larsoner
Copy link
Member

(and for gamma_map IIUC it uses the source space definition with the dipoles pointing out of cortex, which is the direction of the current, which should be positive)

@agramfort
Copy link
Member

agramfort commented Oct 11, 2017 via email

@larsoner
Copy link
Member

Ahh that's true at least some of these are volume. Sure let's just remove (maybe do it in master after merge)

@agramfort
Copy link
Member

ok XXX removed and what's new updated.

good to go on my end if CIs are happy.

@larsoner larsoner merged commit 35eb5be into mne-tools:master Oct 12, 2017
@larsoner
Copy link
Member

Thanks @yousrabk @agramfort

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants