def smooth(self, prop, smoothness=<NUM_LIT:0.5>, weights=None, weight_min=None, weight_transform=None,<EOL>outliers=None, data_range=None, mask=None, valid_range=None, null=np.nan,<EOL>match_distribution=None, transform=None):
<EOL>n = self.tess.vertex_count<EOL>all_vertices = np.asarray(range(n), dtype=np.int)<EOL>(prop,weights) = self.property(prop, outliers=outliers, data_range=data_range,<EOL>mask=mask, valid_range=valid_range,<EOL>weights=weights, weight_min=weight_min,<EOL>weight_transform=weight_transform, transform=transform,<EOL>yield_weight=True)<EOL>prop = np.array(prop)<EOL>if not pimms.is_vector(prop, np.number):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>where_inf = np.where(np.isinf(prop))[<NUM_LIT:0>]<EOL>where_nan = np.where(np.isnan(prop))[<NUM_LIT:0>]<EOL>where_bad = np.union1d(where_inf, where_nan)<EOL>where_ok  = np.setdiff1d(all_vertices, where_bad)<EOL>mask = reduce(np.setdiff1d,<EOL>[all_vertices if mask is None else all_vertices[mask],<EOL>where_nan, np.where(~np.isfinite(weights))[<NUM_LIT:0>]])<EOL>outliers = [] if outliers is None else all_vertices[outliers]<EOL>outliers = np.intersect1d(outliers, mask) <EOL>outliers = np.union1d(outliers, mask[np.where(np.isinf(prop[mask]))[<NUM_LIT:0>]])<EOL>outliers = np.union1d(outliers, mask[np.where(np.isclose(weights[mask], <NUM_LIT:0>))[<NUM_LIT:0>]])<EOL>outliers = np.asarray(outliers, dtype=np.int)<EOL>tethered = np.setdiff1d(mask, outliers)<EOL>tethered = np.asarray(tethered, dtype=np.int)<EOL>mask = np.asarray(mask, dtype=np.int)<EOL>maskset  = frozenset(mask)<EOL>el0 = self.tess.indexed_edges<EOL>prop[outliers] = np.mean(prop[tethered])<EOL>x0 = np.array(prop[mask])<EOL>mask_idx = {v:i for (i,v) in enumerate(mask)}<EOL>mask_tethered = np.asarray([mask_idx[u] for u in tethered])<EOL>el = np.asarray([(mask_idx[a], mask_idx[b]) for (a,b) in el0.T<EOL>if a in maskset and b in maskset])<EOL>(ks, ke) = (smoothness, <NUM_LIT:1.0> - smoothness)<EOL>(zs, ix) = (np.ones(len(el)), np.arange(len(el)))<EOL>e2v = sps.csr_matrix((np.concatenate([zs,-zs]), (el.T.flatten(),np.concatenate([ix, ix]))),<EOL>shape=(len(x0), len(el)), dtype=np.int)<EOL>(us, vs) = el.T<EOL>weights_tth = weights[tethered]<EOL>def _f(x):<EOL><INDENT>rs = np.dot(weights_tth, (x0[mask_tethered] - x[mask_tethered])**<NUM_LIT:2>)<EOL>re = np.sum((x[us] - x[vs])**<NUM_LIT:2>)<EOL>return ks*rs + ke*re<EOL><DEDENT>def _f_jac(x):<EOL><INDENT>df = <NUM_LIT:2>*ke*e2v.dot(x[us] - x[vs])<EOL>df[mask_tethered] += <NUM_LIT:2>*ks*weights_tth*(x[mask_tethered] - x0[mask_tethered])<EOL>return df<EOL><DEDENT>sm_prop = spopt.minimize(_f, x0, jac=_f_jac, method='<STR_LIT>').x<EOL>if match_distribution is not None:<EOL><INDENT>percentiles = <NUM_LIT> * np.argsort(np.argsort(sm_prop)) / (float(len(mask)) - <NUM_LIT:1.0>)<EOL>if match_distribution is True:<EOL><INDENT>sm_prop = np.percentile(x0[mask_tethered], percentiles)<EOL><DEDENT>elif hasattr(match_distribution, '<STR_LIT>'):<EOL><INDENT>sm_prop = np.percentile(match_distribution, percentiles)<EOL><DEDENT>elif hasattr(match_distribution, '<STR_LIT>'):<EOL><INDENT>sm_prop = map(match_distribution, percentiles / <NUM_LIT>)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT><DEDENT>result = np.full(len(prop), null, dtype=np.float)<EOL>result[mask] = sm_prop<EOL>return result<EOL>
mesh.smooth(prop) yields a numpy array of the values in the mesh property prop after they
  have been smoothed on the cortical surface. Smoothing is done by minimizing the square
  difference between the values in prop and the smoothed values simultaneously with the
  difference between values connected by edges. The prop argument may be either a property
  name or a list of property values.

The following options are accepted:
  * weights (default: None) specifies the weight on each individual vertex that is in the
    mesh; this may be a property name or a list of weight values. Any weight that is <= 0 or
    None is considered outside the mask.
  * smoothness (default: 0.5) specifies how much the function should care about the
    smoothness versus the original values when optimizing the surface smoothness. A value of
    0 would result in no smoothing performed while a value of 1 indicates that only the
    smoothing (and not the original values at all) matter in the solution.
  * outliers (default: None) specifies which vertices should be considered 'outliers' in
    that, when performing minimization, their values are counted in the smoothness term but
    not in the original-value term. This means that any vertex marked as an outlier will
    attempt to fit its value smoothly from its neighbors without regard to its original
    value. Outliers may be given as a boolean mask or a list of indices. Additionally, all
    vertices whose values are either infinite or outside the given data_range, if any, are
    always considered outliers even if the outliers argument is None.
  * mask (default: None) specifies which vertices should be included in the smoothing and
    which vertices should not. A mask of None includes all vertices by default; otherwise
    the mask may be a list of vertex indices of vertices to include or a boolean array in
    which True values indicate inclusion in the smoothing. Additionally, any vertex whose
    value is either NaN or None is always considered outside of the mask.
  * data_range (default: None) specifies the range of the data that should be accepted as
    input; any data outside the data range is considered an outlier. This may be given as
    (min, max), or just max, in which case 0 is always considered the min.
  * match_distribution (default: None) allows one to specify that the output values should
    be distributed according to a particular distribution. This distribution may be None (no
    transform performed), True (match the distribution of the input data to the output,
    excluding outliers), a collection of values whose distribution should be matched, or a 
    function that accepts a single real-valued argument between 0 and 1 (inclusive) and
    returns the appropriate value for that quantile.
  * null (default: numpy.nan) specifies what value should be placed in elements of the
    property that are not in the mask or that were NaN to begin with. By default, this is
    NaN, but 0 is often desirable.