def register_retinotopy(hemi,
                        model='benson17', model_hemi=Ellipsis,
                        polar_angle=None, eccentricity=None, weight=None, pRF_radius=None,
                        weight_min=0.1,
                        eccentricity_range=None,
                        partial_voluming_correction=False,
                        radius_weight=1, field_sign_weight=1, invert_rh_field_sign=False,
                        scale=20.0,
                        sigma=Ellipsis,
                        select='close',
                        prior=None,
                        resample=Ellipsis,
                        radius=np.pi/3,
                        max_steps=2000, max_step_size=0.05, method='random',
                        yield_imap=False):
    '''
    register_retinotopy(hemi) registers the given hemisphere object, hemi, to a model of V1, V2,
      and V3 retinotopy, and yields a copy of hemi that is identical but additionally contains
      the registration 'retinotopy', whose coordinates are aligned with the model.

    Registration attempts to align the vertex positions of the hemisphere's spherical surface with a
    model of polar angle and eccentricity. This alignment proceeds through several steps and can
    be modified by several options. A description of these steps and options are provided here. For
    most cases, the default options should work relatively well.

    Method:
      (1) Prepare for registration by several intitialization substeps:
            a. Extract the polar angle, eccentricity and weight data from the hemisphere. These
               data are usually properties on the mesh and can be modifies by the options
               polar_angle, eccentricity, and weight, which can be either property names or list
               of property values. By default (None), a property is chosen using the functions
               neuropythy.vision.extract_retinotopy_argument with the default option set to
               'empirical'.
            b. If partial voluming correction is enabled (via the option
               partial_voluming_correction), multiply the weight by (1 - p) where p is 
               hemi.partial_volume_factor.
            c. If there is a prior that is specified as a belief about the retinotopy, then a
               Registration is created for the hemisphere such that its vertices are arranged
               according to that prior (see also the prior option). Note that because hemi's
               coordinates must always be projected into the registration specified by the model,
               the prior must be the name of a registration to which the model's specified subject
               is also registered. This is clear in the case of an example. The default value for
               this is 'retinotopy'; assuming that our model is specified on the fsaverage_sym, 
               surface, the initial positions of the coordinates for the registration process would
               be the result of starting with hemi's fsaverage_sym-aligned coordinates then warping
               these coordinates in a way that is equivalent to the warping from fsaverage_sym's 
               native spherical coordinates to fsaverage_sym's retinotopy registration coordinates.
               Note that the retinotopy registration would usually be specified in a file in the
               fsaverage_sym subject's surf directory: surf/lh.retinotopy.sphere.reg.
               If no prior is specified (option value None), then the vertices that are used are
               those aligned with the registration of the model, which will usually be 'fsaverage'
               or 'fsaverage_sym'.
            d. If the option resample is not None, then the vertex coordinates are resampled onto
               either the fsaverage or fsaverage_sym's native sphere surface. (The value of resample
               should be either 'fsaverage' or 'fsaverage_sym'.) Resampling can prevent vertices
               that have been rearranged by alignment with the model's specified registration or by
               application of a prior from beginning the alignment with very high initial gradients
               and is recommended for subject alignments.
               If resample is None then no changes are made.
            e. A 2D projection of the (possibly aligned, prior-warped, and resampled) cortical
               surface is made according to the projection parameters of the model. This map is the
               mesh that is warped to eventually fit the model.
      (2) Perform the registration by running neuropythy.registration.mesh_register. This step
          consists of two major components.
            a. Create the potential function, which we will minimize. The potential function is a
               complex function whose inputs are the coordinates of all of the vertices and whose
               output is a potential value that increases both as the mesh is warped and as the
               vertices with retinotopy predictions get farther away from the positions in the model
               that their retinotopy values would predict they should lie. The balance of these
               two forces is best controlled by the option functional_scale. The potential function
               fundamentally consists of four terms; the first three describe mesh deformations and
               the last describes the model fit.
                - The edge deformation term is described for any vertices u and v that are connected
                  by an edge in the mesh; it's value is c/p (r(u,v) - r0(u,v))^2 where c is the
                  edge_scale, p is the number of edges in the mesh, r(a,b) is the distance between
                  vertices a and b, and r0(a,b) is the distance between a and b in the initial mesh.
                - The angle deformation term is described for any three vertices (u,v,w) that form
                  an angle in the mesh; its value is c/m h(t(u,v,w), t0(u,v,w)) where c is the
                  angle_scale argument, m is the number of angles in the mesh, t is the value of the
                  angle (u,v,w), t0 is the value of the angle in the initial mesh, and h(t,t0) is an
                  infinite-well function that asymptotes to positive infinity as t approaches both 0
                  and pi and is minimal when t = t0 (see the nben's 
                  nben.mesh.registration.InfiniteWell documentation for more details).
                - The perimeter term prevents the perimeter vertices form moving significantly;
                  this primarily prevents the mesh from wrapping in on itself during registration.
                  The form of this term is, for any vertex u on the mesh perimeter, 
                  (x(u) - x0(u))^2 where x and x0 are the position and initial position of the
                  vertex.
                - Finally, the functional term is minimized when the vertices best align with the
                  retinotopy model.
            b. Register the mesh vertices to the potential function using the nben Java library. The
               particular parameters of the registration are method, max_steps, and max_step_size.

    Options:
      * model specifies the instance of the retinotopy model to use; this must be an
        instance of the RegisteredRetinotopyModel class or a string that can be passed to the
        retinotopy_model() function (default: 'standard').
      * model_hemi specifies the hemisphere of the model; generally you shouldn't have to set this
        unless you are using an fsaverage_sym model, in which case it should be set to None; in all
        other cases, the default value (Ellipsis) instructs the function to auto-detect the
        hemisphere.
      * polar_angle, eccentricity, pRF_radius, and weight specify the property names for the
        respective quantities; these may alternately be lists or numpy arrays of values. If weight
        is not given or found, then unity weight for all vertices is assumed. By default, each will
        check the  hemisphere's properties for properties with compatible names; it will prefer the
        properties PRF_polar_angle, PRF_ecentricity, and PRF_variance_explained if possible.
      * weight_min (default: 0.1) specifies the minimum value a vertex must have in the weight
        property in order to be considered as retinotopically relevant.
      * eccentricity_range (default: None) specifies that any vertex whose eccentricity is too low
        or too high should be given a weight of 0 in the registration.
      * partial_voluming_correction (default: True), if True, specifies that the value
        (1 - hemi.partial_volume_factor) should be applied to all weight values (i.e., weights
        should be down-weighted when likely to be affected by a partial voluming error).
      * field_sign_weight (default: 1) indicates the relative weight (between 0 and 1) that should
        be given to the field-sign as a method of determining which anchors have the strongest
        springs. A value of 1 indicates that the effective weights of anchors should be the 
        geometric mean of the empirical retinotopic weight and field-sign-based weight; a value of 0
        indicates that no attention should be paid to the field sign weight.
      * radius_weight (default: 1) indicates the relative weight (between 0 and 1) that should
        be given to the pRF radius as a method of determining which anchors have the strongest
        springs. A value of 1 indicates that the effective weights of anchors should be the 
        geometric mean of the empirical retinotopic weight and pRF-radius-based weight; a value of 0
        indicates that no attention should be paid to the radius-based weight.
      * sigma specifies the standard deviation of the Gaussian shape for the Schira model anchors;
        see retinotopy_anchors for more information.
      * scale (default: 1.0) specifies the strength of the functional constraints (i.e. the anchors:
        the part of the minimization responsible for ensuring that retinotopic coordinates are
        aligned); the anatomical constraints (i.e. the edges and angles: the part of the
        minimization responsible for ensuring that the mesh is not overly deformed) are always held
        at a strength of 1.0.
      * select specifies the select option that should be passed to retinotopy_anchors.
      * max_steps (default 2,000) specifies the maximum number of registration steps to run. This
        may be a tuple (max_steps, stride) in which case the registered map that is returned will
        contain a piece of meta-data, 'trajectory' containing the vertex coordinates every stride
        steps of the registration.
      * max_step_size (default 0.05) specifies the maxmim distance a single vertex is allowed to
        move in a single step of the minimization.
      * method (default 'random') is the method argument passed to mesh_register. This should be
        'random', 'pure', or 'nimble'. Generally, 'random' is recommended.
      * yield_imap (default: False) specifies whether the return value should be the new
        Mesh object or a pimms imap (i.e., a persistent mapping of the result of a pimms
        calculation) containing the meta-data that was used during the registration
        calculations. If this is True, then register_retinotopy will return immediately, and
        calculations will only be performed as the relevant data are requested from the returned
        imap. The item 'predicted_mesh' gives the return value when yield_imap is set to False.
      * radius (default: pi/3) specifies the radius, in radians, of the included portion of the map
        projection (projected about the occipital pole).
      * sigma (default Ellipsis) specifies the sigma argument to be passed onto the 
        retinotopy_anchors function (see help(retinotopy_anchors)); the default value, Ellipsis,
        is interpreted as the default value of the retinotopy_anchors function's sigma option.
      * prior (default: None) specifies the prior that should be used, if found, in the 
        topology registrations for the subject associated with the retinotopy_model's registration.
      * resample (default: Ellipsis) specifies that the data should be resampled to one of
        the uniform meshes, 'fsaverage' or 'fsaverage_sym', prior to registration; if None then no
        resampling is performed; if Ellipsis, then auto-detect either fsaverage or fsaverage_sym
        based on the model_hemi option (if it is None, fsaverage_sym, else fsaverage).
    '''
    # create the imap
    m = retinotopy_registration(
        cortex=hemi, model_argument=model, model_hemi=model_hemi,
        polar_angle=polar_angle, eccentricity=eccentricity, weight=weight, pRF_radius=pRF_radius,
        weight_min=weight_min,  eccentricity_range=eccentricity_range,
        partial_voluming_correction=partial_voluming_correction,
        radius_weight=radius_weight, field_sign_weight=field_sign_weight,
        invert_rh_field_sign=invert_rh_field_sign,
        scale=scale, sigma=sigma, select=select, prior=prior, resample=resample, radius=radius,
        max_steps=max_steps, max_step_size=max_step_size, method=method)
    return m if yield_imap else m['predicted_mesh']
register_retinotopy(hemi) registers the given hemisphere object, hemi, to a model of V1, V2,
      and V3 retinotopy, and yields a copy of hemi that is identical but additionally contains
      the registration 'retinotopy', whose coordinates are aligned with the model.

    Registration attempts to align the vertex positions of the hemisphere's spherical surface with a
    model of polar angle and eccentricity. This alignment proceeds through several steps and can
    be modified by several options. A description of these steps and options are provided here. For
    most cases, the default options should work relatively well.

    Method:
      (1) Prepare for registration by several intitialization substeps:
            a. Extract the polar angle, eccentricity and weight data from the hemisphere. These
               data are usually properties on the mesh and can be modifies by the options
               polar_angle, eccentricity, and weight, which can be either property names or list
               of property values. By default (None), a property is chosen using the functions
               neuropythy.vision.extract_retinotopy_argument with the default option set to
               'empirical'.
            b. If partial voluming correction is enabled (via the option
               partial_voluming_correction), multiply the weight by (1 - p) where p is 
               hemi.partial_volume_factor.
            c. If there is a prior that is specified as a belief about the retinotopy, then a
               Registration is created for the hemisphere such that its vertices are arranged
               according to that prior (see also the prior option). Note that because hemi's
               coordinates must always be projected into the registration specified by the model,
               the prior must be the name of a registration to which the model's specified subject
               is also registered. This is clear in the case of an example. The default value for
               this is 'retinotopy'; assuming that our model is specified on the fsaverage_sym, 
               surface, the initial positions of the coordinates for the registration process would
               be the result of starting with hemi's fsaverage_sym-aligned coordinates then warping
               these coordinates in a way that is equivalent to the warping from fsaverage_sym's 
               native spherical coordinates to fsaverage_sym's retinotopy registration coordinates.
               Note that the retinotopy registration would usually be specified in a file in the
               fsaverage_sym subject's surf directory: surf/lh.retinotopy.sphere.reg.
               If no prior is specified (option value None), then the vertices that are used are
               those aligned with the registration of the model, which will usually be 'fsaverage'
               or 'fsaverage_sym'.
            d. If the option resample is not None, then the vertex coordinates are resampled onto
               either the fsaverage or fsaverage_sym's native sphere surface. (The value of resample
               should be either 'fsaverage' or 'fsaverage_sym'.) Resampling can prevent vertices
               that have been rearranged by alignment with the model's specified registration or by
               application of a prior from beginning the alignment with very high initial gradients
               and is recommended for subject alignments.
               If resample is None then no changes are made.
            e. A 2D projection of the (possibly aligned, prior-warped, and resampled) cortical
               surface is made according to the projection parameters of the model. This map is the
               mesh that is warped to eventually fit the model.
      (2) Perform the registration by running neuropythy.registration.mesh_register. This step
          consists of two major components.
            a. Create the potential function, which we will minimize. The potential function is a
               complex function whose inputs are the coordinates of all of the vertices and whose
               output is a potential value that increases both as the mesh is warped and as the
               vertices with retinotopy predictions get farther away from the positions in the model
               that their retinotopy values would predict they should lie. The balance of these
               two forces is best controlled by the option functional_scale. The potential function
               fundamentally consists of four terms; the first three describe mesh deformations and
               the last describes the model fit.
                - The edge deformation term is described for any vertices u and v that are connected
                  by an edge in the mesh; it's value is c/p (r(u,v) - r0(u,v))^2 where c is the
                  edge_scale, p is the number of edges in the mesh, r(a,b) is the distance between
                  vertices a and b, and r0(a,b) is the distance between a and b in the initial mesh.
                - The angle deformation term is described for any three vertices (u,v,w) that form
                  an angle in the mesh; its value is c/m h(t(u,v,w), t0(u,v,w)) where c is the
                  angle_scale argument, m is the number of angles in the mesh, t is the value of the
                  angle (u,v,w), t0 is the value of the angle in the initial mesh, and h(t,t0) is an
                  infinite-well function that asymptotes to positive infinity as t approaches both 0
                  and pi and is minimal when t = t0 (see the nben's 
                  nben.mesh.registration.InfiniteWell documentation for more details).
                - The perimeter term prevents the perimeter vertices form moving significantly;
                  this primarily prevents the mesh from wrapping in on itself during registration.
                  The form of this term is, for any vertex u on the mesh perimeter, 
                  (x(u) - x0(u))^2 where x and x0 are the position and initial position of the
                  vertex.
                - Finally, the functional term is minimized when the vertices best align with the
                  retinotopy model.
            b. Register the mesh vertices to the potential function using the nben Java library. The
               particular parameters of the registration are method, max_steps, and max_step_size.

    Options:
      * model specifies the instance of the retinotopy model to use; this must be an
        instance of the RegisteredRetinotopyModel class or a string that can be passed to the
        retinotopy_model() function (default: 'standard').
      * model_hemi specifies the hemisphere of the model; generally you shouldn't have to set this
        unless you are using an fsaverage_sym model, in which case it should be set to None; in all
        other cases, the default value (Ellipsis) instructs the function to auto-detect the
        hemisphere.
      * polar_angle, eccentricity, pRF_radius, and weight specify the property names for the
        respective quantities; these may alternately be lists or numpy arrays of values. If weight
        is not given or found, then unity weight for all vertices is assumed. By default, each will
        check the  hemisphere's properties for properties with compatible names; it will prefer the
        properties PRF_polar_angle, PRF_ecentricity, and PRF_variance_explained if possible.
      * weight_min (default: 0.1) specifies the minimum value a vertex must have in the weight
        property in order to be considered as retinotopically relevant.
      * eccentricity_range (default: None) specifies that any vertex whose eccentricity is too low
        or too high should be given a weight of 0 in the registration.
      * partial_voluming_correction (default: True), if True, specifies that the value
        (1 - hemi.partial_volume_factor) should be applied to all weight values (i.e., weights
        should be down-weighted when likely to be affected by a partial voluming error).
      * field_sign_weight (default: 1) indicates the relative weight (between 0 and 1) that should
        be given to the field-sign as a method of determining which anchors have the strongest
        springs. A value of 1 indicates that the effective weights of anchors should be the 
        geometric mean of the empirical retinotopic weight and field-sign-based weight; a value of 0
        indicates that no attention should be paid to the field sign weight.
      * radius_weight (default: 1) indicates the relative weight (between 0 and 1) that should
        be given to the pRF radius as a method of determining which anchors have the strongest
        springs. A value of 1 indicates that the effective weights of anchors should be the 
        geometric mean of the empirical retinotopic weight and pRF-radius-based weight; a value of 0
        indicates that no attention should be paid to the radius-based weight.
      * sigma specifies the standard deviation of the Gaussian shape for the Schira model anchors;
        see retinotopy_anchors for more information.
      * scale (default: 1.0) specifies the strength of the functional constraints (i.e. the anchors:
        the part of the minimization responsible for ensuring that retinotopic coordinates are
        aligned); the anatomical constraints (i.e. the edges and angles: the part of the
        minimization responsible for ensuring that the mesh is not overly deformed) are always held
        at a strength of 1.0.
      * select specifies the select option that should be passed to retinotopy_anchors.
      * max_steps (default 2,000) specifies the maximum number of registration steps to run. This
        may be a tuple (max_steps, stride) in which case the registered map that is returned will
        contain a piece of meta-data, 'trajectory' containing the vertex coordinates every stride
        steps of the registration.
      * max_step_size (default 0.05) specifies the maxmim distance a single vertex is allowed to
        move in a single step of the minimization.
      * method (default 'random') is the method argument passed to mesh_register. This should be
        'random', 'pure', or 'nimble'. Generally, 'random' is recommended.
      * yield_imap (default: False) specifies whether the return value should be the new
        Mesh object or a pimms imap (i.e., a persistent mapping of the result of a pimms
        calculation) containing the meta-data that was used during the registration
        calculations. If this is True, then register_retinotopy will return immediately, and
        calculations will only be performed as the relevant data are requested from the returned
        imap. The item 'predicted_mesh' gives the return value when yield_imap is set to False.
      * radius (default: pi/3) specifies the radius, in radians, of the included portion of the map
        projection (projected about the occipital pole).
      * sigma (default Ellipsis) specifies the sigma argument to be passed onto the 
        retinotopy_anchors function (see help(retinotopy_anchors)); the default value, Ellipsis,
        is interpreted as the default value of the retinotopy_anchors function's sigma option.
      * prior (default: None) specifies the prior that should be used, if found, in the 
        topology registrations for the subject associated with the retinotopy_model's registration.
      * resample (default: Ellipsis) specifies that the data should be resampled to one of
        the uniform meshes, 'fsaverage' or 'fsaverage_sym', prior to registration; if None then no
        resampling is performed; if Ellipsis, then auto-detect either fsaverage or fsaverage_sym
        based on the model_hemi option (if it is None, fsaverage_sym, else fsaverage).