-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Inconsistent handling and documentation of pupil size units #12756
Comments
For Eyelink devices (which I guess were our only use-case at the time of writing the doc), eyegaze data are reported in pixels and pupil data are reported in an arbitrary unit (not meters or mm), which, if I recall correctly, is why we wrote that.
You are right that this is incorrect. For example, If a user explicitly converts the eyegaze units from pixels to radians using convert_units, then the eyegaze unit will be SI. But as of now at-least, MNE never tries to convert to an SI unit under the hood on behalf of the user. And we have no function to convert non-SI pupil data to SI. We wanted to eventually implement this, but have yet to get around to it...
|
Thanks for your responses, Scott! tobii stores it in mm, and I have told MNE explicitly via
Whenever I have used tobii, it wasn't done in the same way as with the Eyelink. That is, afaik there is no Tobii eyetracking data format. You can get the variables in realtime via the SDK and then usually save it to file yourself (most often CSV / TSV), only including the aspects of the data that you need. 🤔 but having that said, I am also not too experienced with Tobii. This current data I am working on has been recorded via LSL, so it's in XDF format. |
ah, so we have a bug to fix? 🙂 What error is thrown when you do Because I would expect that
should convert the pupil channel data from millimeters to meters, and set the unit to Then, I would expect |
I think so 👼 Here is a MWE that shows the error. I marked all the bits that I find unexpected. # %%
import numpy as np
import mne
sfreq = 100
n = sfreq + 0 # 10 seconds
ch_names = ["my_pupil"]
ch_types = "pupil"
info = mne.create_info(ch_names, sfreq, ch_types)
mydata = np.atleast_2d(np.random.randint(2, 8, n))
raw = mne.io.RawArray(mydata, info, verbose=False)
ch_type_mapping_eye = {
"my_pupil": ("pupil", "mm", "right"),
}
raw = mne.preprocessing.eyetracking.set_channel_types_eyetrack(raw, ch_type_mapping_eye)
# plots units in AU ... although we set mm ... unexpected
raw.plot()
# ValueError: mm is not a valid unit for pupil, use a sub-multiple of AU instead. ... unexpected
raw.get_data(picks="pupil", units="mm")
# True, as defined and expected
assert mydata.mean() > 2 and mydata.mean() < 8
# AssertionError ... unexpected given the ValueError we got when we tried to get the units in mm
mydata_from_raw = raw.get_data()
assert mydata_from_raw.mean() > 2 and mydata_from_raw.mean() < 8
# True: mean is my_data / 1e3 ... unexpected, because it shows that the units WERE converted from mm to m
assert mydata.mean() / 1e3 == mydata_from_raw.mean()
# %% |
Issue 1
This issue has come up before, We discussed it in #11879 (comment) but I have not been able to get to it yet. The upshot is that until Eyetracking data came along, I think MNE could always hardcode a reasonable scaling for a given channel based on its expected SI unit (e.g. EEG -> volts -> But eye-tracking data can be stored in a standard unit (e.g. Tobii reports pupil size in mm) or in arbitrary units that can't be trivially converted to SI. (e.g. Eyelink reports pupil size in AU). I guess for pupil channels, we chose a default plot scaling that would be best for data that were in arbitrary units.. Currently, the proposed solution is to create a mapping between each possible unit and a suitable scaling factor, then use this mapping in Issue 2
I think this suffers from the same issue... Since Lines 943 to 946 in 868746b
which eventually calls
output
So even though your pupil channel correctly has a unit Issues 3-4
I agree that this is confusing! The mne-python/mne/preprocessing/eyetracking/eyetracking.py Lines 110 to 112 in 868746b
I think/hope that by solving the first two issues, this would be solved too? Side note, we should add a few instances of |
Thanks for looking into it, Scott. This all makes sense to me and I am aware that fixing some of these things will involve a lot of work. I cannot offer this at this point, unfortunately, but hopefully either you, me, or someone else can pick this up in the future.
I think so, too! |
Changing the plotting functions to allow multiple unit types per channel type is doable but I suspect will be (very) hard to get right. In the meantime, a potential in-between solution could be to change the plotting functions from assuming that the SI unit for eyegaze and pupil are This isn't entirely unreasonable, assuming we can settle on the reasonable "standard" SI units. I think |
Thanks both for your input.
I think I am +1 for this:
So to be consistent with ourselves, we can assume the pupil size unit is in meters. The downside to this is that the native values stored by Eyelink are
Most publications report pupil size in We have a function to help users convert their eyegaze data to radians. As long as the visual angle isn't too extreme (<30º), the conversion should be approximately linear. We don't have a function to help Eyelink users convert their pupil size data from AU to meters. It isn't trivial.
Agree!! We have a few different tutorials that cover all of our current functionality. But I'm open to suggestions on how we can improve the documentation. |
This part I'm okay with. People can standardize around one of their first steps being to do this conversion (it probably already is an early step anyway!) then things should work okay. @scott-huberty WDYT about trying to adapt all existing eye tracking tutorials / examples to do this step as early as possible, and then (maybe in the same PR) try changing |
Sure!
Challenge accepted 🏋️ |
Proposed documentation enhancement
In https://mne.tools/dev/documentation/implementation.html, it says that gaze and pupil data are stored in arbitrary units.
However, in https://mne.tools/dev/auto_tutorials/io/70_reading_eyetracking_data.html, it says:
When calling
raw.get_data(picks=["pupil"], unit="mm")
, an error is raised ... however from inspecting my data when getting them withoutunit
, the values DO seem to be in"m"
and I can convert to"mm"
manually by* 1e3
.EDIT: one important caveat: This is data from a Tobii Pro Spectrum 600 that I imported manually into mne ... and I set the units using mne.preprocessing.eyetracking.set_channel_types_eyetrack
The text was updated successfully, but these errors were encountered: