class_docstr: A class for learning a staircase decision tree.
  
  Args:
      domain: The number of points in the domain.
      n_classes: The number of classes.
class_docstr_tok: ["A","class","for","learning","a","staircase","decision","tree",".","Args",":","domain",":","The","number","of","points","in","the","domain",".","n_classes",":","The","number","of","classes","."]
docstr: Fit statistical thresholds for anomaly detection.
  
  This method fits statistical thresholds for anomaly detection based on input data and labels.
  
  Args:
      data (np.ndarray): The input data.
      labels (np.ndarray): The labels corresponding to the data.
      early_stop_after (int, optional): The number of consecutive early stops to consider. Default is 10.
      fixed (bool, optional): Whether to use fixed thresholds. Default is True.
  
  Note:
      This method modifies the internal state of the object to set statistical thresholds.
docstr_tok: ["Fit","statistical","thresholds","for","anomaly","detection",".","This","method","fits","statistical","thresholds","for","anomaly","detection","based","on","input","data","and","labels",".","Args",":","data","(","np.ndarray",")",":","The","input","data",".","labels","(","np.ndarray",")",":","The","labels","corresponding","to","the","data",".","early_stop_after","(","int",",","optional",")",":","The","number","of","consecutive","early","stops","to","consider",".","Default","is","10.","fixed","(","bool",",","optional",")",":","Whether","to","use","fixed","thresholds",".","Default","is","True",".","Note",":","This","method","modifies","the","internal","state","of","the","object","to","set","statistical","thresholds","."]
code: def fit(
      self,
      data: np.ndarray,
      labels: np.ndarray,
      early_stop_after: int = 10,
      fixed: bool = True,
  ) -> None:
      """
      Fit statistical thresholds for anomaly detection.
  
      This method fits statistical thresholds for anomaly detection based on input data and labels.
  
      Args:
          data (np.ndarray): The input data.
          labels (np.ndarray): The labels corresponding to the data.
          early_stop_after (int, optional): The number of consecutive early stops to consider. Default is 10.
          fixed (bool, optional): Whether to use fixed thresholds. Default is True.
  
      Note:
          This method modifies the internal state of the object to set statistical thresholds.
      """
      assert data.ndim == 1
      assert labels.ndim <= 2
      if self.classes == 1:
          self.thresholds = np.array([0.5 + data.max()])
          self.uncertainty = np.zeros_like(self.thresholds)
      if data.ndim == 1:
          data = np.expand_dims(data, 0)
      thresholds = PaddedArray(
          np.insert(
              np.arange(self.domain - self.classes + 1, self.domain)
              - 1,
              [0, self.classes - 1],
              [-0.5, self.domain + 0.5],
          ).astype(int)
      )
      self._back_thres = thresholds.copy()
      self._forward_thres = thresholds.copy()
      self.statistic_fit(data, labels)
      last = -0.5
      for n in range(self.classes):
          G = np.inf
          Gis = deque([], early_stop_after)
          # forward pass
          if n < self.classes - 1:
              new_forward_n: float = self._forward_thres[n]
              for i in range(
                  max(0, self._back_thres[n - 1])
                  if n - 1 >= 0
                  else int(last),
                  min(self.domain, self._forward_thres[n + 1])
                  if n + 2 < self.classes
                  else self.domain - 1,
              ):
                  thresholds.array[n + 1] = i + 0.5
                  Gi = step_impurity(
                      thresholds.array, data, labels, classes=[n, n + 1]
                  )[0]
                  Gis.append(Gi)
                  if Gi <= G:
                      last = i + 0.5
                      new_forward_n = last
                      G = Gi
                  elif (
                      (
                          not fixed
                          or i - last > self.domain / self.classes
                      )
                      and len(Gis) == early_stop_after
                      and all(
                          itertools.starmap(
                              operator.ge,
                              zip(
                                  Gis,
                                  itertools.islice(
                                      Gis, 1, early_stop_after
                                  ),
                              ),
                          )
                      )
                  ):
                      break
              thresholds.array[n + 1] = new_forward_n
              self._forward_thres.array[n + 1] = new_forward_n
              self._back_thres.array[n + 1] = new_forward_n
          G = np.inf
      self._forward_thres = self._forward_thres.toarray().clip(
          min=0, max=self.domain - 1
      )
      self._back_thres = self._back_thres.toarray().clip(
          min=0, max=self.domain - 1
      )
      self.thresholds = (self._forward_thres + self._back_thres) / 2
      self.uncertainty = (
          np.abs(self._forward_thres - self._back_thres) / 2
      )
  
imports: from collections import deque
  import operator
  import itertools
  from typing import Optional, List, Tuple
  import numpy
  import warnings
label_desc: Use image node_id 3 for calling the Staircase obj's underlying member method code with example usage: obj.fit(data, labels, early_stop_after, fixed) without return types