text: """
  Kernel estimation methods.
  """
  
  from numpy import atleast_1d as in1d, atleast_2d as in2d
  from sklearn import neighbors
  import numpy as np
  
  
  ROOT_2PI = np.sqrt(2 * np.pi)
  KERNEL_RADIUS_RATIO = 0.35
  NUM_NEIGHBORS = 10
  
  
  class AdaptiveGaussianKernel(object):
  
      """
      Nearest neighbors method for estimating density or custom functions.
      """
  
      def __init__(self, dataset, values=None, k_neighbors=NUM_NEIGHBORS):
          """Set up the nearest neighbors model for evaluation.
  
          Arguments:
          dataset -- (n,2)-shaped array of spatial points
  
          Keyword arguments:
          values -- scalar values for each point in the dataset
          k_neighbors -- number of neighbors to consider in the model
          """
          dataset = in2d(dataset)
          if dataset.shape[0] == 2:
              dataset = dataset.T
  
          if values is None:
              self.values = np.ones(dataset.shape[0])
          else:
              values = in1d(values)
              if values.ndim != 1:
                  raise ValueError("values can be at most 1-dimensional")
              if values.size != dataset.shape[0]:
                  raise ValueError("size mismatch with values (%d)" % values.size)
              self.values = values
  
          self.model = neighbors.NearestNeighbors(
                  n_neighbors=k_neighbors,
                  algorithm='kd_tree')
          self.model.fit(dataset)
  
      def _Gk(self, dists, radius, kfrac):
          H = kfrac * radius
          G = lambda x: np.exp(-x**2 / (2 * H**2)) / (ROOT_2PI * H)
          return G(dists) - G(radius)
  
      def evaluate(self, points, minrad=0.0, maxrad=100.0, kernel_func=None,
          n_outputs=1, mask_value=np.nan, kernel_ratio=KERNEL_RADIUS_RATIO,
          debug=None):
          """Evaluate the nearest-neighbors model at test points.
  
          Arguments:
          points -- (n,2)-shaped array of test points
  
          Keyword arguments:
          minrad -- minimum allowed kernel radius
          maxrad -- maximum allowed kernel radius
          kernel_func -- neighbor function that produces `n_outputs` values
          n_outputs -- number of outputs generated by the `kernel_func`
          kernel_ratio -- Gaussian kernel size as fraction of radius
  
          Returns:
          (n,)-shaped array, or tuple of arrays (see Notes)
  
          Notes:
          If neither `values` nor `kernel_func` are provided, then this method
          computes a probability density estimate of the data points by default.
  
          If `values` was provided for the training set, then a weighted average
          of these data point values is calculated instead of the density
          estimate.
  
          Providing a kernel function as `kernel_func` can generate multiple
          output evaluations organized along the first axis of the evaluated
          matrix. The kernel function must have the following form:
  
          ```
          def foo(weights, values):
              ...
              return output
          ```
  
          where each argument is a (n,k)-shaped array where `n` is some number of
          test points, `k` is the number of nearest neighbors for that test point,
          and `output` is a (n_outputs,n)-shaped array (or (n,)-shaped if only one
          output). If `values` was not provided, then the argument passed will be
          the nearest-neighbor distances.
          """
          do_density = False
          if kernel_func is None:
              kernel_func = lambda w, v: np.sum(w, axis=-1)
              do_density = True
              n_outputs = 1
  
          points = in2d(points)
          if points.shape[0] == 2:
              points = points.T
  
          L = np.zeros((n_outputs, points.shape[0])) + mask_value
  
          try:
              D, I = self.model.kneighbors(points)
              V = self.values[I]
          except ValueError:
              return L
  
          # Separate adaptive test points from points that hit the bounds
          rad = np.sort(D)[:,-1].reshape(-1,1)
          ihigh = (rad > maxrad).nonzero()[0]
          iadapt = np.logical_and(rad >= minrad, rad <= maxrad).nonzero()[0]
          ilow = (rad < minrad).nonzero()[0]
  
          def eval_fixed_radius(index, radius):
              dists, inds = self.model.radius_neighbors(points[index],
                  radius=radius)
              for i, (d, ix) in enumerate(zip(dists, inds)):
                  vals = self.values[ix]
                  g = self._Gk(d, radius, kernel_ratio)
                  L[:,index[i]] = kernel_func(g, vals)
  
          if ihigh.size:
              eval_fixed_radius(ihigh, maxrad)
  
          if iadapt.size:
              vals = V[iadapt]
              g = self._Gk(D[iadapt], rad[iadapt], kernel_ratio)
              L[:,iadapt] = kernel_func(g, vals)
  
          if ilow.size:
              eval_fixed_radius(ilow, minrad)
  
          L = L.squeeze()
          if debug is not None:
              debug['rad'] = rad
              debug['adapt'] = a = rad.copy()
              a[ilow] = 0
              a[iadapt] = 1
              a[ihigh] = 2
  
          if do_density:
              if np.isnan(L).all():
                  return L
              return L / L[np.isfinite(L)].sum()
  
          return L
  
      __call__ = evaluate
  