def retinotopy_anchors(mesh, mdl,<EOL>polar_angle=None, eccentricity=None,<EOL>weight=None, weight_min=<NUM_LIT:0.1>,<EOL>field_sign_weight=<NUM_LIT:0>, field_sign=None, invert_field_sign=False,<EOL>radius_weight=<NUM_LIT:0>, radius_weight_source='<STR_LIT>', radius=None,<EOL>model_field_sign=None,<EOL>model_hemi=Ellipsis,<EOL>scale=<NUM_LIT:1>,<EOL>shape='<STR_LIT>', suffix=None,<EOL>sigma=[<NUM_LIT:0.1>, <NUM_LIT>, <NUM_LIT>],<EOL>select='<STR_LIT>'):
if pimms.is_str(mdl):<EOL><INDENT>hemi = None<EOL>if pimms.is_str(model_hemi):<EOL><INDENT>model_hemi = model_hemi.upper()<EOL>hemnames = {k:h<EOL>for (h,als) in [('<STR_LIT>', ['<STR_LIT>','<STR_LIT:L>','<STR_LIT>','<STR_LIT>','<STR_LIT>']),<EOL>('<STR_LIT>', ['<STR_LIT>','<STR_LIT:R>','<STR_LIT>','<STR_LIT>','<STR_LIT>'])]<EOL>for k in als}<EOL>if model_hemi in hemnames: hemi = hemnames[model_hemi]<EOL>else: raise ValueError('<STR_LIT>' % model_hemi)<EOL><DEDENT>elif model_hemi is not None:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>mdl = retinotopy_model(mdl, hemi=hemi)<EOL><DEDENT>if not isinstance(mdl, RetinotopyModel):<EOL><INDENT>raise RuntimeError('<STR_LIT>')<EOL><DEDENT>if not isinstance(mesh, geo.Mesh):<EOL><INDENT>raise RuntimeError('<STR_LIT>')<EOL><DEDENT>n = mesh.vertex_count<EOL>X = mesh.coordinates.T<EOL>if weight_min is None: weight_min = <NUM_LIT:0><EOL>(polar_angle, eccentricity, weight) = [<EOL>extract_retinotopy_argument(mesh, name, arg, default='<STR_LIT>')<EOL>for (name, arg) in [<EOL>('<STR_LIT>', polar_angle),<EOL>('<STR_LIT>', eccentricity),<EOL>('<STR_LIT>', np.full(n, weight) if pimms.is_number(weight) else weight)]]<EOL>(polar_angle, eccentricity, weight) = _retinotopy_vectors_to_float(<EOL>polar_angle, eccentricity, weight,<EOL>weight_min=weight_min)<EOL>if np.sum(weight > <NUM_LIT:0>) == <NUM_LIT:0>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>idcs = np.where(weight > <NUM_LIT:0>)[<NUM_LIT:0>]<EOL>select = ['<STR_LIT>', [<NUM_LIT>]] if select == '<STR_LIT>'   else['<STR_LIT>', [<NUM_LIT>]] if select == ['<STR_LIT>'] elseselect<EOL>if select is None:<EOL><INDENT>select = lambda a,b: b<EOL><DEDENT>elif ((pimms.is_vector(select) or is_list(select) or is_tuple(select))<EOL>and len(select) == <NUM_LIT:2> and select[<NUM_LIT:0>] == '<STR_LIT>'):<EOL><INDENT>if pimms.is_vector(select[<NUM_LIT:1>]): d = np.mean(mesh.edge_lengths) * select[<NUM_LIT:1>][<NUM_LIT:0>]<EOL>else:                          d = select[<NUM_LIT:1>]<EOL>select = lambda idx,ancs: [a for a in ancs if a[<NUM_LIT:0>] is not None if npla.norm(X[idx] - a) < d]<EOL><DEDENT>res = mdl.angle_to_cortex(polar_angle[idcs], eccentricity[idcs])<EOL>oks = np.isfinite(np.sum(np.reshape(res, (res.shape[<NUM_LIT:0>], -<NUM_LIT:1>)), axis=<NUM_LIT:1>))<EOL>data = [[[i for _ in r], r, [ksidx[tuple(a)] for a in r]]<EOL>for (i,r0,ok) in zip(idcs, res, oks) if ok<EOL>for ksidx in [{tuple(a):(k+<NUM_LIT:1>) for (k,a) in enumerate(r0)}]<EOL>for r in [select(i, r0)]<EOL>if len(r) > <NUM_LIT:0>]<EOL>idcs = [int(i) for d in data for i in d[<NUM_LIT:0>]]<EOL>ancs = np.asarray([pt for d in data for pt in d[<NUM_LIT:1>]]).T<EOL>labs = np.asarray([ii for d in data for ii in d[<NUM_LIT:2>]]).T<EOL>wgts = np.asarray(weight[idcs] * (<NUM_LIT:1> if scale is None else scale))<EOL>if not np.isclose(field_sign_weight, <NUM_LIT:0>) and mdl.area_name_to_id is not None:<EOL><INDENT>id2n = mdl.area_id_to_name<EOL>if field_sign is True or field_sign is Ellipsis or field_sign is None:<EOL><INDENT>from .cmag import cmag<EOL>r = {'<STR_LIT>': polar_angle,  '<STR_LIT>': eccentricity}<EOL>field_sign = cmag(mesh, r)['<STR_LIT>']<EOL><DEDENT>elif pimms.is_str(field_sign): field_sign = mesh.prop(field_sign)<EOL>field_sign = np.asarray(field_sign)<EOL>if invert_field_sign: field_sign = -field_sign<EOL>fswgts = <NUM_LIT:1.0> - <NUM_LIT> * np.asarray(<EOL>[(fs - visual_area_field_signs[id2n[l]]) if l in id2n else <NUM_LIT:0><EOL>for (l,fs) in zip(labs,field_sign[idcs])])**<NUM_LIT:2><EOL>fswgts = field_sign_weight*fswgts + (<NUM_LIT:1> - field_sign_weight)*wgts<EOL><DEDENT>else: fswgts = None<EOL>if not np.isclose(radius_weight, <NUM_LIT:0>) and mdl.area_name_to_id is not None:<EOL><INDENT>id2n = mdl.area_id_to_name<EOL>emprad = extract_retinotopy_argument(mesh, '<STR_LIT>', radius, default='<STR_LIT>')<EOL>emprad = emprad[idcs]<EOL>emprad = np.argsort(np.argsort(emprad)) * (<NUM_LIT:1.0> / len(emprad)) - <NUM_LIT:0.5><EOL>eccs = eccentricity[idcs]<EOL>prerad = np.asarray([predict_pRF_radius(ecc, id2n[lbl], source=radius_weight_source)<EOL>for (ecc,lbl) in zip(eccs,labs)])<EOL>prerad = np.argsort(np.argsort(prerad)) * (<NUM_LIT:1.0> / len(prerad)) - <NUM_LIT:0.5><EOL>rdwgts = <NUM_LIT:1.0> - (emprad - prerad)**<NUM_LIT:2><EOL>rdwgts = radius_weight*rdwgts + (<NUM_LIT:1>-radius_weight)*wgts<EOL><DEDENT>else: rdwgts = None<EOL>if fswgts is not None:<EOL><INDENT>if rdwgts is not None: wgts = np.power(fswgts*rdwgts*wgts, <NUM_LIT:1.0>/<NUM_LIT>)<EOL>else:                  wgts = np.sqrt(fswgts*wgts)<EOL><DEDENT>elif rdwgts is not None:   wgts = np.sqrt(rdwgts*wgts)<EOL>if sigma is None: sigs = None<EOL>elif pimms.is_number(sigma): sigs = sigma<EOL>elif pimms.is_vector(sigma) and len(sigma) == <NUM_LIT:3>:<EOL><INDENT>[minsig, mult, maxsig] = sigma<EOL>sigs = np.clip(<EOL>[mult*min([npla.norm(a0 - a) for a in anchs if a is not a0]) if len(iii) > <NUM_LIT:1> else maxsig<EOL>for (iii,anchs,_) in data<EOL>for a0 in anchs],<EOL>minsig, maxsig)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>tmp =  (['<STR_LIT>', shape,<EOL>np.asarray(idcs, dtype=np.int),<EOL>np.asarray(ancs, dtype=np.float64),<EOL>'<STR_LIT>', np.asarray(wgts, dtype=np.float64)]<EOL>+ ([] if sigs is None else ['<STR_LIT>', sigs])<EOL>+ ([] if suffix is None else suffix))<EOL>return tmp<EOL>
retinotopy_anchors(mesh, model) is intended for use with the mesh_register function and the
retinotopy_model() function and/or the RetinotopyModel class; it yields a description of the
anchor points that tie relevant vertices the given mesh to points predicted by the given model
object. Any instance of the RetinotopyModel class should work as a model argument; this includes
SchiraModel objects as well as RetinotopyMeshModel objects such as those returned by the
retinotopy_model() function. If the model given is a string, then it is passed to the
retinotopy_model() function first.

Options:
  * polar_angle (default None) specifies that the given data should be used in place of the
    'polar_angle' or 'PRF_polar_angle'  property values. The given argument must be numeric and
    the same length as the the number of vertices in the mesh. If None is given, then the
    property value of the mesh is used; if a list is given and any element is None, then the
    weight for that vertex is treated as a zero. If the option is a string, then the property
    value with the same name isused as the polar_angle data.
  * eccentricity (default None) specifies that the given data should be used in places of the
    'eccentricity' or 'PRF_eccentricity' property values. The eccentricity option is handled 
    virtually identically to the polar_angle option.
  * weight (default None) specifies that the weight or scale of the data; this is handled
    generally like the polar_angle and eccentricity options, but may also be 1, indicating that
    all vertices with polar_angle and eccentricity values defined will be given a weight of 1.
    If weight is left as None, then the function will check for 'weight',
    'variance_explained', 'PRF_variance_explained', and 'retinotopy_weight' values and will use
    the first found (in that order). If none of these is found, then a value of 1 is assumed.
  * weight_min (default 0) specifies that the weight must be higher than the given value inn
    order to be included in the fit; vertices with weights below this value have their weights
    truncated to 0.
  * scale (default 1) specifies a constant by which to multiply all weights for all anchors; the
    value None is interpreted as 1.
  * shape (default 'Gaussian') specifies the shape of the potential function (see mesh_register)
  * model_hemi (default: None) specifies the hemisphere of the model to load; if None, then
    looks for a non-specific model.
  * suffix (default None) specifies any additional arguments that should be appended to the 
    potential function description list that is produced by this function; i.e., the 
    retinotopy_anchors function produces a list, and the contents of suffix, if given and not
    None, are appended to that list (see mesh_register).
  * select (default 'close') specifies a function that will be called with two arguments for
    every vertex given an anchor; the arguments are the vertex label and the matrix of anchors.
    The function should return a list of anchors to use for the label (None is equivalent to
    lambda id,anc: anc). The parameter may alternately be specified using the string 'close':
    select=['close', [k]] indicates that any anchor more than k times the average edge-length in
    the mesh should be excluded; a value of just ['close', k] on the other hand indicates that
    any anchor more than k distance from the vertex should be exlcuded. The default value,
    'close', is equivalent to ['close', [40]].
  * sigma (default [0.1, 2.0, 4.0]) specifies how the sigma parameter should be handled; if
    None, then no sigma value is specified; if a single number, then all sigma values are
    assigned that value; if a list of three numbers, then the first is the minimum sigma value,
    the second is the fraction of the minimum distance between paired anchor points, and the 
    last is the maximum sigma --- the idea with this form of the argument is that the ideal
    sigma value in many cases is approximately 0.25 to 0.5 times the distance between anchors
    to which a single vertex is attracted; for any anchor a to which a vertex u is attracted,
    the sigma of a is the middle sigma-argument value times the minimum distance from a to all
    other anchors to which u is attracted (clipped by the min and max sigma).
  * field_sign_weight (default: 0) specifies the amount of weight that should be put on the
    retinotopic field of the model as a method of attenuating the weights on those anchors whose
    empirical retinotopic values and predicted model locations do not match. The weight that
    results is calculated from the difference in empirical field-sign for each vertex and the
    visual area field sign based on the labels in the model. The higher the field-sign weight,
    (approaching 1) the more the resulting value is a geometric mean of the field-sign-based
    weight and the original weights. As this value approaches 0, the resulting weights are more
    like the original weights.
  * radius_weight (default: 0) specifies the amount of weight that should be put on the
    receptive field radius of the model as a method of attenuating the weights on those anchors
    whose empirical retinotopic values and predicted model locations do not match. The weight
    that results is calculated from the difference in empirical RF radius for each vertex and
    the predicted RF radius based on the labels in the model. The higher the radius weight,
    (approaching 1) the more the resulting value is a geometric mean of the field-sign-based
    weight and the original weights. As this value approaches 0, the resulting weights are more
    like the original weights.
  * radius_weight_source (default: 'Wandell2015') specifies the source for predicting RF radius;
    based on eccentricity and visual area label.

Example:
 # The retinotopy_anchors function is intended for use with mesh_register, as follows:
 # Define our Schira Model:
 model = neuropythy.registration.SchiraModel()
 # Make sure our mesh has polar angle, eccentricity, and weight data:
 mesh.prop('polar_angle',  polar_angle_vertex_data);
 mesh.prop('eccentricity', eccentricity_vertex_data);
 mesh.prop('weight',       variance_explained_vertex_data);
 # register the mesh using the retinotopy and model:
 registered_mesh = neuropythy.registration.mesh_register(
    mesh,
    ['mesh', retinotopy_anchors(mesh, model)],
    max_step_size=0.05,
    max_steps=2000)