def areal_cmag(mesh, retinotopy='any', mask=None, surface_area=None, weight=None, nnearest=None):
    '''
    areal_cmag(obj) yields an areal cortical magnification function for the given vertex-set object
      or mapping of retinotopy data obj. If obj is a mapping of retinotopy data, then it must also
      contain the key 'surface_area' specifying the surface area of each vertex in mm^2.

    The areal cmag function is a measurement of how much surface area in a retinotopy dataset is
    found within a circle found in the visual field. The size of the circle is chosen automatically
    by looking up the <n> nearest neighbors of the point in question, summing their surface areas,
    and dividing by the area of the circle in the visual field that is big enough to hold them.

    The returned object cm = areal_cmag(obj) is a special cortical magnification object that can be
    called as cm(x, y) or cm(coord) where x and y may be lists or values and coord may be a 2D
    vector or an (n x 2) matrix. The yielded value(s) will always be in units mm^2 / deg^2.

    The following options may be provided (also in argument order):
      * retinotopy (default: 'any') specifies the retinotopy data to be used; this is passed to
        the retinotopy_data function with the mesh.
      * mask (default: None) specifies the mask that should be used; this is interpreted by a call
        to mesh.mask(mask)
      * surface_area (default: 'midgray_surface_area') specifies the vertex area property that
        should be used; this is interpreted by a call to mesh.property(surface_area) so may be
        either a property name or a list of values
      * weight (default: None) specifies additional weights that should be used; this is generally
        discouraged
      * nnearest (default: None) specifies the number of nearest neighbors to search for when
        calculating the magnification; if None, then uses int(numpy.ceil(numpy.sqrt(n) * np.log(n)))
        where n is the number of vertices included in the mask
    '''
    # First, find the retino data
    retino = retinotopy_data(mesh, retinotopy)
    # Convert from polar angle/eccen to longitude/latitude
    (ang,ecc) = as_retinotopy(retino, 'visual')
    # get the surface area
    if surface_area is None: surface_area = 'midgray_surface_area'
    if pimms.is_str(surface_area):
        if surface_area in retino: surface_area = retino[surface_area]
        elif geo.is_vset(mesh):    surface_area = mesh.property(surface_area)
        else:                      surface_area = mesh[surface_area]
    # get the weight
    if weight is not None:
        if pimms.is_str(weight):
            if weight in retino:    weight = retino[weight]
            elif geo.is_vset(mesh): weight = mesh.property(weight)
            else:                   weight = mesh[weight]
    wgt = next((retino[q] for q in ('variance_explained', 'weight') if q in retino), None)
    # Get the indices we care about
    ii = geo.to_mask(mesh, mask, indices=True)
    ii = ii[np.isfinite(ang[ii]) & np.isfinite(ecc[ii])]
    # get our nnearest
    if nnearest is None: nnearest = int(np.ceil(np.sqrt(len(ii)) * np.log(len(ii))))
    return ArealCorticalMagnification(ang[ii], ecc[ii], surface_area[ii],
                                      weight=(None if wgt is None else wgt[ii]),
                                      nnearest=nnearest)
areal_cmag(obj) yields an areal cortical magnification function for the given vertex-set object
      or mapping of retinotopy data obj. If obj is a mapping of retinotopy data, then it must also
      contain the key 'surface_area' specifying the surface area of each vertex in mm^2.

    The areal cmag function is a measurement of how much surface area in a retinotopy dataset is
    found within a circle found in the visual field. The size of the circle is chosen automatically
    by looking up the <n> nearest neighbors of the point in question, summing their surface areas,
    and dividing by the area of the circle in the visual field that is big enough to hold them.

    The returned object cm = areal_cmag(obj) is a special cortical magnification object that can be
    called as cm(x, y) or cm(coord) where x and y may be lists or values and coord may be a 2D
    vector or an (n x 2) matrix. The yielded value(s) will always be in units mm^2 / deg^2.

    The following options may be provided (also in argument order):
      * retinotopy (default: 'any') specifies the retinotopy data to be used; this is passed to
        the retinotopy_data function with the mesh.
      * mask (default: None) specifies the mask that should be used; this is interpreted by a call
        to mesh.mask(mask)
      * surface_area (default: 'midgray_surface_area') specifies the vertex area property that
        should be used; this is interpreted by a call to mesh.property(surface_area) so may be
        either a property name or a list of values
      * weight (default: None) specifies additional weights that should be used; this is generally
        discouraged
      * nnearest (default: None) specifies the number of nearest neighbors to search for when
        calculating the magnification; if None, then uses int(numpy.ceil(numpy.sqrt(n) * np.log(n)))
        where n is the number of vertices included in the mask