-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
WIP: loose parameter as dict #4312
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #4312 +/- ##
==========================================
- Coverage 82.82% 82.61% -0.22%
==========================================
Files 349 349
Lines 64424 65196 +772
Branches 9915 10153 +238
==========================================
+ Hits 53361 53860 +499
- Misses 8324 8540 +216
- Partials 2739 2796 +57 |
mne/forward/forward.py
Outdated
|
|
||
| def _check_loose(forward, loose): | ||
| """Check loose parameter input.""" | ||
| if is_fixed_orient(forward): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it mean I always have a warning when working with fixed ori?
I think we should not have a warning when user set loose to None explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added and loose is not None, so the warning will now only appear if loose is not None
| """Check loose parameter input.""" | ||
| if is_fixed_orient(forward) and loose is not None: | ||
| warn('Ignoring loose parameter with forward operator ' | ||
| 'with fixed orientation.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Say to set it to None to avoid this warning
mne/forward/forward.py
Outdated
| if not (0 <= loose <= 1): | ||
| raise ValueError('Loose value should be smaller than 1 and ' | ||
| 'bigger than 0, or None for not loose ' | ||
| 'orientations.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
say what you got
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joewalter reminder here
mne/forward/forward.py
Outdated
| raise ValueError('Loose value should be smaller than 1 and ' | ||
| 'bigger than 0, or None for not loose ' | ||
| 'orientations.') | ||
| if loose < 1 and not forward['surf_ori']: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say
if loose is not None and not forward['surf_ori']:
mne/forward/forward.py
Outdated
| orient_prior[np.mod(np.arange(n_sources), 3) != 2] *= loose | ||
|
|
||
| if ((loose is not None) and | ||
| not all([item in [1., None] for item in loose.values()])): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should force loose=None rather than accepting 1.
| noise_cov, depth=None) | ||
|
|
||
| # for free ori inv, loose=None and loose=1 should be equivalent | ||
| # for free ori inv, loose=None and loose=1. should be equivalent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Eric89GXL are you ok to force loose=None for non surf ori forward?
|
Why not just always use float? It seems cleaner to me.
|
|
None is more explicit to say "ignore this param"
|
|
Maybe from an internal coding perspective. But it seems less explicit to
the user in terms of what the effective value / outcome is, and less simple
in terms of values accepted.
To put it differently, in the future if we have a parameter in another
function that varies smoothly between two extremes, where one extreme
effectively does nothing, should we always disallow that extreme value and
force people to use None?
|
|
... For example, any regularization parameter.
|
|
The one way I can see it making sense is if for free orientation forward
None meant "don't modify", and for fixed orientation None also meant "don't
modify", but in that case we shouldn't disallow the equivalent numerical
value (0 or 1) in either case.
|
|
we shouldn't disallow the equivalent numerical value (0 or 1) in either
case.
ok for me but I would document / recommend the use of None.
|
|
Do we want to allow a loose orientation constraint for discrete source spaces? IIRC they are used for defining volume source spaces, so I am wondering whether we should treat them similarly to volume source spaces? |
|
I would say no. Loose ori only makes sense for surface oriented source spaces
Alex
|
|
I would say yes. Discrete shouldn't be used for volumes, volume type should
be used for that. IIUC discrete is used for anything custom the user wants,
and normals can easily be properly defined there. In fact the only two
things the user provides for Discrete type are locations and normals.
|
|
ok for me then as long as volume does not use discrete source space
|
|
Argh, we do have these lines: So we change I think this use case is likely rare (?), but the case of user-defined discrete source spaces might also be rare. To be safe, I'm okay with forcing free ori for |
|
Ok, I'll force free orientation with my next commit. |
|
With regard to sparse solvers I thought of normalizing the vector (weight_tan1, weight_tan2, weight_normal) in order not to bias the solution towards sources with free orientation (I'd add a sparse_inv flag, so that nothing changes for MNE-type methods) |
Why wouldn't you also want this for MNE methods, at least as an option? That way if I have 1000 fixed-orientation surface source-space points and 1000 free-orientation volume points, you could achieve roughly equivalent activation mapping into both (spatial distribution considerations aside), right? |
|
same concern as Eric. It seems like a bug
to work differently with L2 or sparse solvers.
|
|
So the variance of a source depends on whether it is a free or fixed orientation source? |
|
When we agree to only support loose or fixed orientation for surface-based source spaces, we can make the handling of loose much simpler, as we don't need the dict (so the check_loose function is much simpler) and we just add an info that loose parameter is ignored for volume and discrete source spaces. |
|
we could do this for now until there is a motivation to have loose for
discrete source space.
let's keep it simple
|
|
Sounds like a plan. Does this also take care of #4313? Is it possible/easy to update some example? Even a mixed-source-space MNE example might benefit from it. |
mne/forward/forward.py
Outdated
| 'orientation.') | ||
| forward = convert_forward_solution(forward, surf_ori=True) | ||
| else: | ||
| raise ValueError('loose value must be None for not loose ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
loose must be None for not loose orientations ?
this is unclear what you mean here.
| else: | ||
| logger.info('Applying loose dipole orientations for surface-based ' | ||
| 'source spaces with loose=%f.' % loose) | ||
| idx_start = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add here
assert not is_fixed_orient(forward)
to avoid futur bugs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any time to come back to this one, too? It'll need a (probably annoying) rebase
| assert_true(_check_loose(fwd_fixed, 0.2)[1] is None) | ||
|
|
||
| del fwd, fwd_fixed | ||
| gc.collect() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you are really worried about memory, convert_forward_solution has copy=False to modify inplace
|
|
||
| @testing.requires_testing_data | ||
| def test_check_loose(): | ||
| """Test _check_loose |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
end with period, no newline before """ (we are slowly updating to latest docstring standard)
|
@joewalter what is left here? Just a rebase and a few minor remaining comments? |
|
I don't think we should do this until 0.16 so we have some time to finish and then test, pushing to 0.16 |
|
I think it is a good idea to push this to 0.16 so we have enough time for improvements and tests |
|
let's not close. We'll take some code from here. |
|
I think to make this one easier, we could split it in several PR. So we can faster merge parts of it, making rebasing simpler |
|
yes agreed
|
|
Perhaps the first split could take care of #4604. That would be nice to have for 0.15 |
|
Removing 0.16 tag |
|
@joewalter any time to come back to this one? |
|
This PR is way out of date at this point. Now that almost all code is refactored to use the same |
WIP addressing #2163 and #4308.
Added a new private function, which checks the input to loose and adapts it if necessary (and also converts forward to surface oriented if required). Currently, only loose = None and loose=1. are supported for vol source spaces. Please let me know if loose orientation constraint should also be available for vol source spaces.