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

Let pybv write [coordinates] section to vhdr files #44

Open
sappelhoff opened this issue Jul 19, 2020 · 4 comments
Open

Let pybv write [coordinates] section to vhdr files #44

sappelhoff opened this issue Jul 19, 2020 · 4 comments
Labels
effort:medium estimated medium effort task enhancement New feature or request impact:medium estimated medium impact task
Milestone

Comments

@sappelhoff
Copy link
Member

sappelhoff commented Jul 19, 2020

See BrainVision data file specification.

The OPTIONAL [Coordinates] section in a vhdr file comes right after the REQUIRED [Channels] section, and it looks like this:

[Coordinates]
; Each entry: Ch<Channel number>=<Radius>,<Theta>,<Phi>
Ch1=1,-60,-51
Ch2=1,-49,-29
Ch3=1,-45,0
Ch4=1,-49,29

For the radius, the spec say the following [emphasis by me]:

“The radius r specifies the distance (in millimeters) between point P and the origin of the coordinate system. The only exceptions are r = 0 and r = 1. r = 0 signifies an invalid position, for instance when the position of an electrode is not known. When realistic electrode coordinates are used, r can have a different value for each channel. In other cases, the value of r should be the same for all the channels if a spherical head model is used. For instance, in the Analyzer's standard coordinate system, r = 1”.

All coordinates that pybv writes to the [Coordinates] section must first be transformed to the Analyzer's standard coordinate system, which happens to be the CapTrak system (more info in FieldTrip wiki). For this conversion to work, we will need the Nasion, left, and right preauricular point coordinates (to rescale the coordsystem).

I suggest that furthermore, pybv writes a more extensive comment in the [Coordinates] section:

[Coordinates]
; Each entry: Ch<Channel number>=<Radius>,<Theta>,<Phi>
; Radius defined in millimeters (mm).
; Radius of 0 signifies invalid position for a given electrode.
; If all coordinates are on an (idealized) spherical head model, Radius will be 1 for all entries.
; The coordinate system is "Captrak", see definition of axes below.
; The X-axis goes from the left preauricular point towards (through) the right preauricular point.
; The Y-axis goes orthogonally to the X-axis and towards (through) the nasion.
; The Z-axis goes orthogonally to the X-Y-plane upwards.
; Below are the coordinates for left and right preauricular points, and the nasion.
; LPA=1,44,55
; RPA=1,44,55
; Nasion=1,44,55
Ch1=1,-60,-51
Ch2=1,-49,-29
Ch3=1,-45,0
Ch4=1,-49,29
@sappelhoff sappelhoff added enhancement New feature or request good first issue Good for newcomers labels Jul 19, 2020
@sappelhoff sappelhoff modified the milestones: 0.4.0, 0.5.0 Nov 5, 2020
@sappelhoff sappelhoff modified the milestones: 0.5.0, 0.6.0 Dec 29, 2020
@sappelhoff
Copy link
Member Author

sappelhoff commented Apr 3, 2021

this will be particularly interesting once MNE starts to export to pybv ... because we'll want to capture as much of the FIF data as possible for a round-trip.

@sappelhoff sappelhoff added effort:medium estimated medium effort task impact:medium estimated medium impact task and removed good first issue Good for newcomers labels Aug 6, 2021
@sappelhoff
Copy link
Member Author

sappelhoff commented Aug 8, 2021

as discussed in #77, the input for a coordinates parameter in write_brainvision could be a list of dicts:

[
    {
        "name": "LPA",
        "x": 0.3,
        "y": 4.5,
        "z": 6.1,
    },
    {
        "name": "Fpz",
        "radius": 3.1,
        "theta": 22,
        "phi": 33,
    }
]

pybv would then:

  • check that an entry has either a complete set of "x, y, z" OR a complete set of "radius, theta, phi"
  • convert XYZ to radius, theta phi (because we write radius, theta, phi to VMRK)
  • check for "LPA", "RPA", and "Nasion", and write them as "comment" (because VHDR only supports existing data channels in their coordinate section; see my example)
    • also use LPA, RPA, NAS for transforming the coordinate system to "head" (=captrak, =analyzer)
  • check for all other "names" and map them to channel indices as present in the data (we write indices, not names to VHDR)
  • raise a warning if there are more or less names than in the data
  • if less names, the missing names are entered with zeros (that is the "NaN" representation in VHDR)
  • if more names, the superfluous names are just ignored

PS: I have a very lengthy email discussion on this topic with Brain Products that I didn't post here ... But I think what we plan here would be spec conformant: Especially if we put coordsystem info, units, and landmarks as "comments".

BV Readers can then optionally check the VHDR for whether the file was created by "pybv" and if it was, make use of that "comment".

BV Readers that dont check for that, will still get sensible data: At least as sensible as the underspecified "Coordinates" section allows :-)

@hoechenberger
Copy link
Collaborator

This sounds great!

@sappelhoff
Copy link
Member Author

we'd probably need to look at these three functions in mne

  • get_ras_to_neuromag_trans
  • compute_native_head_t
  • transform_to_head

and simplify them for use here without adding mne as a dependency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort:medium estimated medium effort task enhancement New feature or request impact:medium estimated medium impact task
Projects
None yet
Development

No branches or pull requests

2 participants