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

DigMontages: information on coordinate systems; Document transform_to_head in API docs #12904

Open
sappelhoff opened this issue Oct 21, 2024 · 2 comments

Comments

@sappelhoff
Copy link
Member

sappelhoff commented Oct 21, 2024

I just got some sensor positions in a text file that are in the "CTF" coordinate system. Naturally, I wanted to turn this into a DigMontage. However, when trying to find an appropriate value for the coord_frame parameter, I was faced with two choices:

  1. ctf_meg
  2. ctf_head

I could not easily find any documentation on the differences between these two coordinate systems. Ideally we would have a page where each coordinate system that we support is described with mentioning at least the origin, and the direction of the three axes (x,y,z) with reference to fiducials/anatomical landmarks, wherever possible. What do you think?

Furthermore, I think mne.channels.DigMontage should get a method called .transform_to (or similar) that takes as input the string label of any supported coordinate system in mne. Alternatively (or additionally), this functionality could also become a parameter upon instantiation of the DigMontage. .apply_trans seems a bit tricky to use for that. Opinions on this?

@larsoner
Copy link
Member

I could not easily find any documentation on the differences between these two coordinate systems. Ideally we would have a page where each coordinate system that we support is described with mentioning at least the origin, and the direction of the three axes (x,y,z) with reference to fiducials/anatomical landmarks, wherever possible. What do you think?

Rather than add our own I'd prefer to point to this as it seems like an excellent reference

https://www.fieldtriptoolbox.org/faq/coordsys/

But adding a table with this minimal information for the coord frames we support plus a link to that FAQ would work, too!

Furthermore, I think mne.channels.DigMontage should get a method called .transform_to (or similar) that takes as input the string label of any supported coordinate system in mne. Alternatively (or additionally), this functionality could also become a parameter upon instantiation of the DigMontage. .apply_trans seems a bit tricky to use for that. Opinions on this?

Typically in MNE we have tried to just get sensor positions to the Neuromag head coordinate frame as much as possible. And it happens automatically when you do .set_montage(...) I think.

We could expand this, at least for (probably?) ctf_head. For other stuff like ctf_meg it would be more complicated because then you'd actually need the transformation between CTF head and device coordinate frames, like you'd have to do .transform_to("ctf_meg", transform=mne.transform.Transform("ctf_head", "ctf_meg", <some ndarray>) or similar. Or at least I think this would be the case without having reread all the coord frame definitions...

@sappelhoff
Copy link
Member Author

@larsoner I actually found that we already do have a function to rescale to "head", it is just not exposed:

def transform_to_head(montage):
"""Transform a DigMontage object into head coordinate.
Parameters
----------
montage : instance of DigMontage
The montage.
Returns
-------
montage : instance of DigMontage
The montage after transforming the points to head
coordinate system.
Notes
-----
This function requires that the LPA, RPA and Nasion fiducial
points are available. If they are not, they will be added based by
projecting the fiducials onto a sphere with radius equal to the average
distance of each point to the origin (in the given coordinate frame).
This function assumes that all fiducial points are in the same coordinate
frame (e.g. 'unknown') and it will convert all the point in this coordinate
system to Neuromag head coordinate system.
.. versionchanged:: 1.2
Fiducial points will be added automatically if the montage does not
have them.
"""
# Get fiducial points and their coord_frame
native_head_t = compute_native_head_t(montage)
montage = montage.copy() # to avoid inplace modification
if native_head_t["from"] != FIFF.FIFFV_COORD_HEAD:
for d in montage.dig:
if d["coord_frame"] == native_head_t["from"]:
d["r"] = apply_trans(native_head_t, d["r"])
d["coord_frame"] = FIFF.FIFFV_COORD_HEAD
_ensure_fiducials_head(montage.dig)
return montage

https://mne.tools/stable/search.html?q=transform_to_head

Can we perhaps expose this function and document it in our API?

And it happens automatically when you do .set_montage(...) I think.

yes, that is the only time this function is called outside of tests.

def _get_montage_in_head(montage):
coords = set([d["coord_frame"] for d in montage.dig])
montage = montage.copy()
if len(coords) == 1 and coords.pop() == FIFF.FIFFV_COORD_HEAD:
_ensure_fiducials_head(montage.dig)
return montage
else:
return transform_to_head(montage)

def _set_montage(info, montage, match_case=True, match_alias=False, on_missing="raise"):
"""Apply montage to data.
With a DigMontage, this function will replace the digitizer info with
the values specified for the particular montage.
Usually, a montage is expected to contain the positions of all EEG
electrodes and a warning is raised when this is not the case.
Parameters
----------
%(info_not_none)s
%(montage)s
%(match_case)s
%(match_alias)s
%(on_missing_montage)s
Notes
-----
This function will change the info variable in place.
"""
_validate_type(montage, (DigMontage, None, str), "montage")
if montage is None:
# Next line modifies info['dig'] in place
with info._unlock():
info["dig"] = None
for ch in info["chs"]:
# Next line modifies info['chs'][#]['loc'] in place
ch["loc"] = np.full(12, np.nan)
return
if isinstance(montage, str): # load builtin montage
_check_option(
parameter="montage",
value=montage,
allowed_values=[m.name for m in _BUILTIN_STANDARD_MONTAGES],
)
montage = make_standard_montage(montage)
mnt_head = _get_montage_in_head(montage)
del montage

@sappelhoff sappelhoff changed the title DigMontages: information on coordinate systems; and adding a simple rescaling method DigMontages: information on coordinate systems; Document transform_to_head in API docs Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants