class_docstr: Region-aware form of the sampling path.
  
  Uses region points to guess a likelihood contour gradient.
class_docstr_tok: ["Region-aware","form","of","the","sampling","path",".","Uses","region","points","to","guess","a","likelihood","contour","gradient","."]
docstr: Compute gradient approximation.
  
  Finds spheres enclosing the `reflpoint`, and chooses their mean
  as the direction to go towards. If no spheres enclose the
  reflpoint, use nearest sphere.
  
  v is not used, because that would break detailed balance.
  
  Considerations:
     - in low-d, we want to focus on nearby live point spheres
       The border traced out is fairly accurate, at least in the
       normal away from the inside.
  
     - in high-d, reflpoint is contained by all live points,
       and none of them point to the center well. Because the
       sampling is poor, the "region center" position
       will be very stochastic.
  
  Parameters
  -----------
  reflpoint: vector
      point outside the likelihood contour, reflect there
  v: vector
      previous direction vector
  
  Returns
  ---------
  gradient: vector
      normal of ellipsoid
docstr_tok: ["Compute","gradient","approximation",".","Finds","spheres","enclosing","the","`","reflpoint","`",",","and","chooses","their","mean","as","the","direction","to","go","towards",".","If","no","spheres","enclose","the","reflpoint",",","use","nearest","sphere",".","v","is","not","used",",","because","that","would","break","detailed","balance",".","Considerations",":","-","in","low-d",",","we","want","to","focus","on","nearby","live","point","spheres","The","border","traced","out","is","fairly","accurate",",","at","least","in","the","normal","away","from","the","inside",".","-","in","high-d",",","reflpoint","is","contained","by","all","live","points",",","and","none","of","them","point","to","the","center","well",".","Because","the","sampling","is","poor",",","the","``","region","center","''","position","will","be","very","stochastic",".","Parameters","--","--","--","--","--","-","reflpoint",":","vector","point","outside","the","likelihood","contour",",","reflect","there","v",":","vector","previous","direction","vector","Returns","--","--","--","--","-","gradient",":","vector","normal","of","ellipsoid"]
code: def gradient(self, reflpoint, plot=False):
      """Compute gradient approximation.
  
      Finds spheres enclosing the `reflpoint`, and chooses their mean
      as the direction to go towards. If no spheres enclose the
      reflpoint, use nearest sphere.
  
      v is not used, because that would break detailed balance.
  
      Considerations:
         - in low-d, we want to focus on nearby live point spheres
           The border traced out is fairly accurate, at least in the
           normal away from the inside.
  
         - in high-d, reflpoint is contained by all live points,
           and none of them point to the center well. Because the
           sampling is poor, the "region center" position
           will be very stochastic.
  
      Parameters
      -----------
      reflpoint: vector
          point outside the likelihood contour, reflect there
      v: vector
          previous direction vector
  
      Returns
      ---------
      gradient: vector
          normal of ellipsoid
  
      """
      if plot:
          plt.plot(reflpoint[0], reflpoint[1], "+ ", color="k", ms=10)
  
      # check which the reflections the ellipses would make
      region = self.region
      bpts = region.transformLayer.transform(reflpoint.reshape((1, -1)))
      dist = ((bpts - region.unormed) ** 2).sum(axis=1)
      assert dist.shape == (len(region.unormed),), (
          dist.shape,
          len(region.unormed),
      )
      nearby = dist < region.maxradiussq
      assert nearby.shape == (len(region.unormed),), (
          nearby.shape,
          len(region.unormed),
      )
      if not nearby.any():
          nearby = dist == dist.min()
      sphere_centers = region.u[nearby, :]
  
      tsphere_centers = region.unormed[nearby, :]
      nlive, ndim = region.unormed.shape
      assert tsphere_centers.shape[1] == ndim, (
          tsphere_centers.shape,
          ndim,
      )
  
      # choose mean among those points
      tsphere_center = tsphere_centers.mean(axis=0)
      assert tsphere_center.shape == (ndim,), (
          tsphere_center.shape,
          ndim,
      )
      tt = get_sphere_tangent(tsphere_center, bpts.flatten())
      assert tt.shape == tsphere_center.shape, (
          tt.shape,
          tsphere_center.shape,
      )
  
      # convert back to u space
      sphere_center = region.transformLayer.untransform(tsphere_center)
      t = (
          region.transformLayer.untransform(tt * 1e-3 + tsphere_center)
          - sphere_center
      )
  
      if plot:
          tt_all = get_sphere_tangent(tsphere_centers, bpts)
          t_all = (
              region.transformLayer.untransform(
                  tt_all * 1e-3 + tsphere_centers
              )
              - sphere_centers
          )
  
          """
              # plot in transformed space too:
              origax = plt.gca()
              ax = plt.axes([0.7, 0.7, 0.27, 0.27])
              plt.plot(bpts[:,0], bpts[:,1], '+ ', color='k', ms=10)
              plt.plot(region.unormed[:,0], region.unormed[:,1], 'x ', color='k', ms=4)
              plt.plot(tsphere_centers[:,0], tsphere_centers[:,1], 'o ', mfc='None', mec='b', ms=10, mew=1)
              for si, ti in zip(tsphere_centers, tt_all):
                  plt.plot([si[0], ti[0] + si[0]], [si[1], ti[1] + si[1]], '--', lw=2, color='gray', alpha=0.5)
              plt.plot(tsphere_center[0], tsphere_center[1], '^ ', mfc='None', mec='g', ms=10, mew=3)
              plt.plot([tsphere_center[0], tt[0] + tsphere_center[0]],
                  [tsphere_center[1], tt[1] + tsphere_center[1]], lw=1, color='gray')
              plt.sca(origax)
              """
  
          plt.plot(
              sphere_centers[:, 0],
              sphere_centers[:, 1],
              "o ",
              mfc="None",
              mec="b",
              ms=10,
              mew=1,
          )
          if not (dist < region.maxradiussq).any():
              plt.plot(
                  sphere_centers[:, 0],
                  sphere_centers[:, 1],
                  "s ",
                  mfc="None",
                  mec="b",
                  ms=10,
                  mew=1,
              )
          for si, ti in zip(sphere_centers, t_all):
              plt.plot(
                  [si[0], ti[0] * 1000 + si[0]],
                  [si[1], ti[1] * 1000 + si[1]],
                  "--",
                  lw=2,
                  color="gray",
                  alpha=0.5,
              )
          plt.plot(
              sphere_center[0],
              sphere_center[1],
              "^ ",
              mfc="None",
              mec="g",
              ms=10,
              mew=3,
          )
          plt.plot(
              [sphere_center[0], t[0] * 1000 + sphere_center[0]],
              [sphere_center[1], t[1] * 1000 + sphere_center[1]],
              color="gray",
          )
  
      # compute new vector
      normal = t / norm(t)
      isunitlength(normal)
      assert normal.shape == t.shape, (normal.shape, t.shape)
  
      return normal
  
imports: import numpy
  from numpy.linalg import norm
  import matplotlib.pyplot
label_desc: Use image node_id 5 for calling the ContourSamplingPath obj's underlying member method code with example usage: obj.gradient(reflpoint, plot) and returns: normal