class_docstr: Robust random cut tree data structure as described in:
  
  S. Guha, N. Mishra, G. Roy, & O. Schrijvers. Robust random cut forest based anomaly
  detection on streams, in Proceedings of the 33rd International conference on machine
  learning, New York, NY, 2016 (pp. 2712-2721).
  
  Parameters:
  -----------
  X: np.ndarray (n x d) (optional)
     Array containing n data points, each with dimension d.
     If no data provided, an empty tree is created.
  index_labels: sequence of length n (optional) (default=None)
                Labels for data points provided in X.
                Defaults to [0, 1, ... n-1].
  precision: float (optional) (default=9)
             Floating-point precision for distinguishing duplicate points.
  random_state: int, RandomState instance or None (optional) (default=None)
      If int, random_state is the seed used by the random number generator;
      If RandomState instance, random_state is the random number generator;
      If None, the random number generator is the RandomState instance used by np.random.
  
  Attributes:
  -----------
  root: Branch or Leaf instance
        Pointer to root of tree.
  leaves: dict
          Dict containing pointers to all leaves in tree.
  ndim: int
        dimension of points in the tree
  
  Methods:
  --------
  insert_point: inserts a new point into the tree.
  forget_point: removes a point from the tree.
  disp: compute displacement associated with the removal of a leaf.
  codisp: compute collusive displacement associated with the removal of a leaf
          (anomaly score).
  map_leaves: traverses all nodes in the tree and executes a user-specified
              function on the leaves.
  map_branches: traverses all nodes in the tree and executes a user-specified
                function on the branches.
  query: finds nearest point in tree.
  get_bbox: find bounding box of points under a given node.
  find_duplicate: finds duplicate points in the tree.
  
  Example:
  --------
  # Create RCTree
  >>> X = np.random.randn(100,2)
  >>> tree = RCTree(X)
  
  # Insert a point
  >>> x = np.random.randn(2)
  >>> tree.insert_point(x, index=100)
  
  # Compute collusive displacement of new point (anomaly score)
  >>> tree.codisp(100)
  
  # Remove point
  >>> tree.forget_point(100)
class_docstr_tok: ["Robust","random","cut","tree","data","structure","as","described","in",":","S.","Guha",",","N.","Mishra",",","G.","Roy",",","&","O.","Schrijvers",".","Robust","random","cut","forest","based","anomaly","detection","on","streams",",","in","Proceedings","of","the","33rd","International","conference","on","machine","learning",",","New","York",",","NY",",","2016","(","pp",".","2712-2721",")",".","Parameters",":","--","--","--","--","--","-","X",":","np.ndarray","(","n","x","d",")","(","optional",")","Array","containing","n","data","points",",","each","with","dimension","d.","If","no","data","provided",",","an","empty","tree","is","created",".","index_labels",":","sequence","of","length","n","(","optional",")","(","default=None",")","Labels","for","data","points","provided","in","X.","Defaults","to","[","0",",","1",",","...","n-1","]",".","precision",":","float","(","optional",")","(","default=9",")","Floating-point","precision","for","distinguishing","duplicate","points",".","random_state",":","int",",","RandomState","instance","or","None","(","optional",")","(","default=None",")","If","int",",","random_state","is","the","seed","used","by","the","random","number","generator",";","If","RandomState","instance",",","random_state","is","the","random","number","generator",";","If","None",",","the","random","number","generator","is","the","RandomState","instance","used","by","np.random",".","Attributes",":","--","--","--","--","--","-","root",":","Branch","or","Leaf","instance","Pointer","to","root","of","tree",".","leaves",":","dict","Dict","containing","pointers","to","all","leaves","in","tree",".","ndim",":","int","dimension","of","points","in","the","tree","Methods",":","--","--","--","--","insert_point",":","inserts","a","new","point","into","the","tree",".","forget_point",":","removes","a","point","from","the","tree",".","disp",":","compute","displacement","associated","with","the","removal","of","a","leaf",".","codisp",":","compute","collusive","displacement","associated","with","the","removal","of","a","leaf","(","anomaly","score",")",".","map_leaves",":","traverses","all","nodes","in","the","tree","and","executes","a","user-specified","function","on","the","leaves",".","map_branches",":","traverses","all","nodes","in","the","tree","and","executes","a","user-specified","function","on","the","branches",".","query",":","finds","nearest","point","in","tree",".","get_bbox",":","find","bounding","box","of","points","under","a","given","node",".","find_duplicate",":","finds","duplicate","points","in","the","tree",".","Example",":","--","--","--","--","#","Create","RCTree",">",">",">","X","=","np.random.randn","(","100,2",")",">",">",">","tree","=","RCTree","(","X",")","#","Insert","a","point",">",">",">","x","=","np.random.randn","(","2",")",">",">",">","tree.insert_point","(","x",",","index=100",")","#","Compute","collusive","displacement","of","new","point","(","anomaly","score",")",">",">",">","tree.codisp","(","100",")","#","Remove","point",">",">",">","tree.forget_point","(","100",")"]
code: def __init__(
      self, X=None, index_labels=None, precision=9, random_state=None
  ):
      # Random number generation with provided seed
      if isinstance(random_state, int):
          self.rng = np.random.RandomState(random_state)
      elif isinstance(random_state, np.random.RandomState):
          self.rng = random_state
      else:
          self.rng = np.random
      # Initialize dict for leaves
      self.leaves = {}
      # Initialize tree root
      self.root = None
      self.ndim = None
      if X is not None:
          # Round data to avoid sorting errors
          X = np.around(X, decimals=precision)
          # Initialize index labels, if they exist
          if index_labels is None:
              index_labels = np.arange(X.shape[0], dtype=int)
          self.index_labels = index_labels
          # Check for duplicates
          U, I, N = np.unique(
              X, return_inverse=True, return_counts=True, axis=0
          )
          # If duplicates exist, take unique elements
          if N.max() > 1:
              n, d = U.shape
              X = U
          else:
              n, d = X.shape
              N = np.ones(n, dtype=int)
              I = None
          # Store dimension of dataset
          self.ndim = d
          # Set node above to None in case of bottom-up search
          self.u = None
          # Create RRC Tree
          S = np.ones(n, dtype=bool)
          self._mktree(X, S, N, I, parent=self)
          # Remove parent of root
          self.root.u = None
          # Count all leaves under each branch
          self._count_all_top_down(self.root)
          # Set bboxes of all branches
          self._get_bbox_top_down(self.root)
  
imports: import numpy
label_desc: Use image node_id 1 to create a new RCTree object  with example: obj = RCTree(X, index_labels, precision, random_state)