top of page

Delineating retinotopic maps in human visual cortex

This tutorial demonstrates how to create region-of-interest labels for retinotopic regions V1 through V3 from polar angle maps using freeview. The pipeline for obtaining these maps from raw brain data can be found at https://github.com/ddcoggan/p013_retinotopy.


Requirements:

  • Freesurfer installed and accessible from the command line

  • A clean freesurfer segmentation, particularly the white matter surface

  • A map of the polar angle representation in surface space


First, we need to load up the polar angle map on the inflated surface. This is done below using python to build a freeview command, but can be done in directly in the command line if preferred:


import os
import os.path as op
import matplotlib as mpl
import numpy as np

# configure the data to display
subject = 'M015'
session = '7T1'
hemi = 'rh'
colormap = ['colorwheel', 'red_yellow_green'][0]

# path to subject's freesurfer dir and inflated surface
fs_subj_dir = f'{os.environ["SUBJECTS_DIR"]}/sub-{subject}'
surface = f'{fs_subj_dir}/surf/{hemi}.inflated'

# path to directory where polar angle map is stored
overlay = op.abspath(f'derivatives/pRF/sub-{subject}/ses-{session}/polar_angle_{hemi}.mgh')

# if you wish to restrict the polar angle map to a region, choose which label reflects this region
mask = f'derivatives/ROIs/sub-{subject}/ses-{session}/mask_analyzed_{hemi}.label'

# colormap where vertical meridians are marked with red (90) and green (270)
if colormap == 'red_yellow_green':
    cmap = (
        '0,255,255,0,'
        '45,255,255,0,'
        '90,255,0,0,'
        '135,255,255,0,'
        '180,255,255,0,'
        '225,255,255,0,'
        '270,0,255,0,'
        '315,255,255,0,'
        '360,255,255,0')

# colorwheel (hsv where right horizontal meridian (0) is red)
else:
    colors = np.linspace(0, 1, 37)
    if hemi == 'lh':  # flip colormap as datamap was previously flipped
        colors = -(colors + .5) % 1
    colorwheel = np.hstack((
        np.linspace(0, 360, 37, dtype=int).reshape(-1, 1),
        np.array(mpl.colormaps['hsv'](colors) * 255, int)[:,:-1]))
    cmap = ','.join(
        [','.join([str(i) for i in row]) for row in colorwheel])

# make the freeview command
cmd = (
    f'freeview '
    f'-f {surface}'
    f':overlay={overlay}'
    f':curvature_method=binary'
    f':overlay_custom={cmap} '
    f':overlay_mask={mask} '
    f'-layout 1 -viewport 3d')

# execute the command
os.system(cmd)

Executing this code should bring up something like this (colorwheel added for reference):



We can see that the right hemisphere represents the contralateral left visual field (90°-270°). With the exception of the V1d/V1v border, borders between different visual regions are marked by reversals in the polar angle map (e.g., the purple line at the occipital pole, which is the V1d/V2d border).


From here, we can start marking out primary visual cortex, either as a single region containing an entire hemifield (V1) or two quarterfields of the dorsal and ventral aspects (V1d, V1v). To delineate a region, click the 'Path/Custom Fill' icon (black triangle with red points), then make a path around the region. For instance, here is an outline of V1d:



To connect the points, click the 'Make Closed Path' icon (black triangle with pencil). The smaller the distance between points, the more you can constrain the path to be exactly where you want it. Then select somewhere inside the path (Ctrl + Shift + click), which will place the red cursor inside the path. It should look like this:



To convert this region into a label, click the 'Custom Fill' icon (paint can), which will bring up this window:



Ensure these options are selected, then click 'Fill'. This should fill the region with a color and a new label should be visible in the label menu to the left of the display. Save this label as whatever you like (TongLab formatting would be 'rh.tong.V1d'. You can then begin on the next region. Do not worry about overlap when delineating along the border of a previous region, as the fill conditions above can be controlled to prevent overlap between regions. The path for V1v could therefore be something like this (yellow outline):



When you fill with the same options as before, you would get the following label, which does not overlap with V1d:



Continue to create labels for all the regions that you can confidently delineate. Here's how I would delineate V1-V3:



That's it! You now have a set of labels that you can use as regions of interest in surface-space analyses or, alternatively, convert them into voxel masks to use them in volumetric space analyses (e.g. using freesurfer's 'mri_label2vol').



9 views0 comments

Comments


bottom of page