docs: def _tree_grow(self, y_true, X, cost_mat, level=0):
          """ Private recursive function to grow the decision tree.
  
          Parameters
          ----------
          y_true : array indicator matrix
              Ground truth (correct) labels.
  
          X : array-like of shape = [n_samples, n_features]
              The input samples.
  
          cost_mat : array-like of shape = [n_samples, 4]
              Cost matrix of the classification problem
              Where the columns represents the costs of: false positives, false negatives,
              true positives and true negatives, for each example.
  
          Returns
          -------
          Tree : Object
              Container of the decision tree
              NOTE: it is not the same structure as the sklearn.tree.tree object
  
          """
  
          #TODO: Find error, add min_samples_split
          if len(X.shape) == 1:
              tree = dict(y_pred=y_true, y_prob=0.5, level=level, split=-1, n_samples=1, gain=0)
              return tree
  
          # Calculate the best split of the current node
          split, gain, Xl_pred, y_pred, y_prob = self._best_split(y_true, X, cost_mat)
  
          n_samples, n_features = X.shape
  
          # Construct the tree object as a dictionary
  
          #TODO: Convert tree to be equal to sklearn.tree.tree object
          tree = dict(y_pred=y_pred, y_prob=y_prob, level=level, split=-1, n_samples=n_samples, gain=gain)
  
          # Check the stopping criteria
          if gain < self.min_gain:
              return tree
          if self.max_depth is not None:
              if level >= self.max_depth:
                  return tree
          if n_samples <= self.min_samples_split:
              return tree
          
          j, l = split
          filter_Xl = (X[:, j] <= l)
          filter_Xr = ~filter_Xl
          n_samples_Xl = np.nonzero(filter_Xl)[0].shape[0]
          n_samples_Xr = np.nonzero(filter_Xr)[0].shape[0]
  
          if min(n_samples_Xl, n_samples_Xr) <= self.min_samples_leaf:
              return tree
  
          # No stooping criteria is met
          tree['split'] = split
          tree['node'] = self.tree_.n_nodes
          self.tree_.n_nodes += 1
  
          tree['sl'] = self._tree_grow(y_true[filter_Xl], X[filter_Xl], cost_mat[filter_Xl], level + 1)
          tree['sr'] = self._tree_grow(y_true[filter_Xr], X[filter_Xr], cost_mat[filter_Xr], level + 1)
  
          return tree