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
ENH: monopole source model #603
base: main
Are you sure you want to change the base?
Conversation
Thank you for this contribution. I will try to review it in the coming weeks, but it will have probably to wait a bit because I'm mostly unavailable in the next 2/3 weeks (I'll try to do my best). Thank's again. |
Could you give a write access to your clone of OpenMEEG, so that I can push some corrections directly on your branch. Alternatively, I can clone your branch and give you access write. What do you prefer. |
Or alternatively @harmening you could click the "give edit access to maintainers" button on the PR. But it's enabled by default I think so unless you un-checked it when opening the PR you should be able to push already @papadop ... |
@papadop did you try pushing? I think it should already work: |
Yes I tried a simple correction and it failed, that's why I'm aslking. |
OK. I just retried. It works.... |
OK. With my very small change, most builders pass. I will do a code review in the coming days/weeks. If, in the meantime, you can contribute the tests I was referring to, that would be nice.... Thank's again.... |
Hey, thanks for the fast reply. I added a simple test as in the dsm case, please let me know if you're satisfied or if you'd like to have sth more (sophisticated). Also haven't added any python tests for the msm case yet, could do so if you wish |
…nction it turns out it computes the barycentric coordinates of the passed point (aka the P1 function values). The formar code was working but very cryptic. It is replaced by a simple 2d linear system solved with least squares. This is both faster (3-4%), requires less memory (but this is not a problem) and clearer (because the code is more compact, because of the renaming of the class and because of the addition of some comments explaining what is done).
Hello. Thank you again for your contribution. I did a code review of your proposal and pushed some changes. I think we are mostly good, but I have a final set of questions for you....
|
… order to have all tests passing.
…e logical. Slight names imprvements.
Missing .monop files that prevented exiting tests to pass are now added. |
|
||
return -EMpart*P1part; // RK: why - sign ? | ||
return -EMpart*P1term; // RK: why - sign ? |
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 agree with this - very old - comment.. I saw that in the analyticMonopolePotDer follows this sign change (at line 246 there should be a minus sign - per the mathematical formula - which is not there) . Did you do it to match the sign here, or have you validated by some other mean (comparison with some ground truth, or analysis of the code at the upper level) that this sign change is needed.
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 do not really know where the sign question comes from because I do not know your derivations but I am sure it is correct that the monopole has opposite sign in this sense here. The monopole derivative is -1/4pi q@r/|r|^3 while the dipole is 1/4pi (q/|r|^3-3q@r/|r|^5*r)
const double b2 = dotprod(r21,u); | ||
const double l = b1*c22-b2*c12; | ||
const double m = b2*c11-b1*c12; | ||
return Vect3(l,m,1-l-m); | ||
} |
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 changed all of this code, because honestly I was not able to understand what it did from the formula. And there was no comment to explain it. The new version is explained and costs less (both in space, which is not very crucial, but also in time). I verified that it gave strictly the same results. A further improvement would be to completely eliminate this calculations. Indeed, we compute the points using barycentric coordinates and then pass the points to these functions... to re-compute the barycentric coordinates. It would be simpler to pass directly the barycentric coodinates and to recompute the point in the analytic functions. I will do this in another PR.
0 0 0.7650 1 | ||
0 0 0.8075 1 | ||
0 0 0.8415 1 | ||
0 0 0.8075 1.5 |
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.
Comment for the line below. You provided the Head1/Head1.msm, which is most probably the expected result of the test. Can we add some comparison test that checks that the output of the test is indeed that one.
I'm also interested on how this file was obtained. If this is by running the OpenMEEG code, we will just check that the code always provide the same result. If the values were obtained with another numerical model, then we might check that the obtained values are indeed those that are expected. I suspect that we are in the former case... See the comments on the PR, for more suggestions on tests to add.
And obviously, we nedd that for Hed2. Head3, HeadMN*, HeadNN{a,b,c}*, ....
|
||
# om_assemble -MSM geometry.geom conductivity.cond monooples.monop msm.bin | ||
|
||
OPENMEEG_TEST(MSM-${SUBJECT} ${ASSEMBLE} -MSM ${GEOM} ${COND} ${MONOPPOS} ${MSMMAT} DEPENDS CLEAN-TESTS) | ||
|
||
# om_assemble -DSM geometry.geom conductivity.cond dipoles.dip dsm.bin | ||
|
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 we also add comparison tests. See OPENMEEG_COMPARISON_TEST.
Thanks for you detailed code review!
|
could we have a unit test comparing the solution to some ground truth
values obtained in a sphere model or with some alternative reference solver?
… Message ID: ***@***.***>
|
We will try to implement this. I would go for a sphere model with a single source. Do you think single or multisphere. Single is of course much easier. |
You can add multiple tests. Sphere is fine. Both single shell ans multiple shells would be great.... If you need ground truth for multiple shells, I can probably help. |
Help wanted, I never actually simulated any spheres and don't know any solver not built for dipoles. I can work it out myself but why if you offer help? ;D |
I have some software that is able to extend the solution in infinite homogenous medium to multiple spheres. I just need to investigate what is the spherical harmonics decomposition of the monpole potential.... |
I have been thinking about this today a little bit:
|
Hey, @papadop, are you working on a reference solution or shall I also? I got that you had something that should be easy to adopt so I was waiting but could of course also proceed implementing something. Thanks anways :) |
we found a solution: this toolbox models mulitlayered spheres for monopoles. https://github.com/femeg/FEMEG/blob/master/femeg_anisphere.m
Are you fine with that approach? What error measures would you want? Do you have a template test that does something similar we can use to adopt? We need to run several commands to build the leadfield (om_assemble for headmodel, msm and sensor interpolation). |
Hey @papadop, what do you think about our approach of storing the analytic monopole solution in binary files for the different heads and testing the openmeeg code against them? Or do you have any concerns? I was also thinking about implementing the analytic solution here, too, but I think that's a bit overshooting the mark, isn't it? |
@papadop @larsoner @agramfort, sorry to bother you again, but it feels like we're stuck at this point. I would still love to see our changes merged to finally enable the community to use HArtMuTs simulation of EEG artifacts. We have pending PRs prepared for fieldtrip and eeglab's dipfit once MSM is merged. Please let me summarize, what we have here so far:
We were discussing about adding further tests, like testing against analytic solutions, solutions by some alternative reference solver, or testing the solutions of dipoles to those of two very close monopoles. Since we could not proceed any further on how to implement further tests for almost one year now, what do you think about merging this branch finally and opening up a new thread/issue for the implementation of further testing. I agree that the discussed tests make totally sense and I am also willing to help implementing that (also because we already compared monopoles in spherical models against the analytic solution as provided by FEMEG), but I need help in constructing such a test within this framework here. I am very much looking forward to your response! Would be really really great if we could somehow move forward :-) |
I have no objection, hopefully @papadop or @agramfort can weigh in In the meantime I'll merge |
Enhancement: Adding the monopole source model.
With monopoles, more complex source models can be constructed like tripoles for muscular sources or any arbitrary source configuration. The EMG of muscular sources contributes in EEG as artifacts and due to the proximity of sources and sensors is potentially better approximated by a near field tripolar solution (further details: HArtMuT).
Thus, OpenMEEG users would not only be able to simulate cortical activity but also EEG artifacts like muscular activity more realistically.
OpenMEEG/include/monopole.h
, add monopole class.OpenMEEG/include/analytics.h
, add potential derivative.OpenMEEG/src/assembleSourceMat.cpp
, add MonopSoureMat (analogously to DipSourceMat).OpenMEEG/src/operators.cpp
, add operatorMonopolePot and operatorMonopolePotDer (analogously to operatorDipolePot and -Der).apps/assemble.cpp
, add -MonopSourceMat (-MSM) (analogously to -DipSourceMat (-DSM)).wrapping/python/openmeeg/__init__.py
, add MonopSourceMat (analogously to DipSourceMat).