def get_roi_masks(subject,xfmname,roi_list=None,dst=2,fail_for_missing_rois=False):
    '''Return a numbered mask + dictionary of roi numbers

    This function returns a single 3D array with a separate numerical index for each ROI, 

    Parameters
    ----------
    subject : string
        pycortex subject ID
    xfmname : string
        pycortex transformation name
    roi_list : list or None
        list of names of ROIs to retrieve (e.g. ['FFA','OFA','EBA']). Names should match the 
        ROI layers in the rois.svg file for the `subject` specified. If None is provided (default),
        all available ROIs for the subject are returned.
    dst : scalar or string
        Distance from fiducial surface to define ROI. Reasonable values are ~1 (very conservative)
        to ~3 (lots of brain that isn't cortex). Alternatively, you can specify one of the available 
        masks as the dst value ('thick','thin', or 'cortical'). 'cortical' will only work if the 
        surface for `subject` was created using Freesurfer.
    fail_for_missing_rois : bool
        Whether to fail if one or more of the rois specified in roi_list are not available. If set to
        False (default behavior), requested rois that are not present will be ignored (and not included
        in the outputs, obviously)
    
    Returns
    -------
    mask : array
        Single 3D array with a separate numerical index value for each ROI. ROI index values in the 
        left hemisphere are negative. (For example, if V1 in the right hemisphere is 1, then V1 in 
        the left hemisphere will be -1). 
    roi_index : dict
        Mapping of roi names to index values (e.g. {'V1': 1}). 
    '''
    # Get ROIs from inkscape SVGs
    rois, vert_idx = db.get_overlay(subject, remove_medial=True)

    # Retrieve shape from the reference
    shape = db.get_xfm(subject, xfmname).shape
    
    # Get 3D coordinates
    coords = np.vstack(db.get_coords(subject, xfmname)) # UGH. Replace with a mapper object (IDK what this comment is...)
    n_verts = np.max(coords.shape)
    coords = coords[vert_idx]
    n_valid_vertices = np.max(coords.shape)
    # Get distance of each voxel from fiducial surface (vox_dst) and index for each voxel showing 
    # which surface vertex is closest to it (vox_idx). Note that vox_idx includes vertices on the 
    # medial wall, which later need to be excluded from the ROIs.
    vox_dst,vox_idx = get_vox_dist(subject,xfmname)
    vox_idx_flat = vox_idx.flatten()
    # Get L,R hem separately
    L,R = db.get_surf(subject, "flat", merge=False, nudge=True)
    nL = len(np.unique(L[1]))
    # Mask for left hemisphere
    Lmask = (vox_idx < nL).flatten()
    Rmask = np.logical_not(Lmask)
    if type(dst) in (str,unicode):
        cx_mask = db.get_mask(subject,xfmname,dst).flatten()
    else:
        cx_mask = (vox_dst < dst).flatten()
    
    if roi_list is None:
        roi_list = rois.names
    else:
        roi_list = [r for r in roi_list if r in ['Cortex','cortex']+rois.names]
        if fail_for_missing_rois:
            fails = [r for r in roi_list if not r in ['Cortex','cortex']+rois.names]
            if any(fails):
                for f in fails:
                    print("No ROI exists for %s"%f)
                raise ValueError("Invalid ROIs requested!")

    if isinstance(roi_list, str):
        roi_list = [roi_list]
    # First: get all roi voxels into 4D volume
    tmp_mask = np.zeros((np.prod(shape),len(roi_list),2),np.bool)
    drop_roi = []
    for ir,roi in enumerate(roi_list):
        if roi.lower()=='cortex':
            roi_idx_bin3 = np.ones(Lmask.shape)>0
        else:
            # Complicated indexing to remove vertices/voxels on the medial wall
            roi_idx_bin1 = np.zeros((n_valid_vertices,),np.bool) # binary index 1
            # This step is the time-consuming step, which can't be avoided.
            roi_idx_sub1 = rois.get_roi(roi) # substitution index 1 (in valid vertex space)
            roi_idx_bin1[roi_idx_sub1] = True
            roi_idx_bin2 = np.zeros((n_verts,),np.bool) # binary index 2
            roi_idx_bin2[vert_idx] = roi_idx_bin1
            roi_idx_sub2 = np.nonzero(roi_idx_bin2)[0] # substitution index 2 (in ALL fiducial vertex space)
            roi_idx_bin3 = np.in1d(vox_idx_flat,roi_idx_sub2) # binary index to 3D volume (flattened, though)
        tmp_mask[:,ir,0] = np.all(np.array([roi_idx_bin3,Lmask,cx_mask]),axis=0)
        tmp_mask[:,ir,1] = np.all(np.array([roi_idx_bin3,Rmask,cx_mask]),axis=0)
        if not np.any(tmp_mask[:,ir]):
            drop_roi += [ir]
    # Cull rois with no voxels
    keep_roi = np.array([not ir in drop_roi for ir in range(len(roi_list))],dtype=np.bool)
    # Cull rois requested, but not avialable in pycortex
    roi_list_L = [r for ir,r in enumerate(roi_list) if not ir in drop_roi]
    tmp_mask = tmp_mask[:,keep_roi,:]
    # Kill all overlap btw. "cortex" and other ROIs
    roi_list_L_lower = [xx.lower() for xx in roi_list_L]
    if 'cortex' in roi_list_L_lower:
        cx_idx = roi_list_L_lower.index('cortex')
        # Left:
        other_rois = tmp_mask[:,np.arange(len(roi_list_L))!=cx_idx,0] 
        tmp_mask[:,cx_idx,0] = np.logical_and(np.logical_not(np.any(other_rois,axis=1)),tmp_mask[:,cx_idx,0])
        # Right:
        other_rois = tmp_mask[:,np.arange(len(roi_list_L))!=cx_idx,1]
        tmp_mask[:,cx_idx,1] = np.logical_and(np.logical_not(np.any(other_rois,axis=1)),tmp_mask[:,cx_idx,1])

    # Second: 
    mask = np.zeros(np.prod(shape),dtype=np.int64)
    roi_idx = {}
    to_cut = np.sum(tmp_mask,axis=1)>1
    # Note that indexing by vox_idx guarantees that there will be no overlap in ROIs
    # (unless there are overlapping assignments to ROIs on the surface), due to 
    # each voxel being assigned only ONE closest vertex
    print('%d overlapping voxels were cut'%np.sum(to_cut))
    tmp_mask[to_cut] = False 
    for ir,roi in enumerate(roi_list_L):
        mask[tmp_mask[:,ir,0]] = -ir-1
        mask[tmp_mask[:,ir,1]] = ir+1
        roi_idx[roi] = ir+1
    mask.shape = shape

    return mask,roi_idx
dataset/ETHPy150Open gallantlab/pycortex/cortex/utils.py/get_roi_masks/original