code: def build(self, X, y):
      val, feat, stat = self._get_best_split(X, y)
      splits = LifoQueue()
      splits.put((val, feat, stat, 0, np.arange(X.shape[0])))
  
      node_stats = []
      while splits.qsize() > 0:
          val, feat, stat, lvl, idx = splits.get()
          s = {
              "feature": feat,
              "threshold": val,
              "n_node_samples": idx.shape[0],
              "statistic": stat,
              "depth": lvl,
          }
          node_stats.append(s)
  
          if val == TREE_UNDEFINED:
              continue
  
          left = X[idx, feat] <= val
          right = idx[~left]
          left = idx[left]
  
          if lvl == self.max_depth - 1:
              splits.put(
                  [
                      TREE_UNDEFINED,
                      TREE_UNDEFINED,
                      -np.infty,
                      lvl + 1,
                      right,
                  ]
              )
              splits.put(
                  [
                      TREE_UNDEFINED,
                      TREE_UNDEFINED,
                      -np.infty,
                      lvl + 1,
                      left,
                  ]
              )
              continue
  
          X_right = X[right, :]
          y_right = y[right]
          s_right = self._get_best_split(X_right, y_right)
          splits.put(list(s_right) + [lvl + 1, right])
  
          X_left = X[left, :]
          y_left = y[left]
          s_left = self._get_best_split(X_left, y_left)
          splits.put(list(s_left) + [lvl + 1, left])
  
      return pd.DataFrame.from_dict(
          dict(zip(range(len(node_stats)), node_stats)), orient="index"
      )
  
imports: from itertools import product
  from queue import LifoQueue
  import numpy
  from numpy.testing import assert_array_almost_equal, assert_array_equal
  import pandas
  import pytest
  from scipy import sparse
  from sklearn.model_selection import train_test_split
  from sklearn.pipeline import make_pipeline
  from sklearn.preprocessing import OrdinalEncoder
  from sklearn.tree._tree import TREE_UNDEFINED
  from sksurv.compare import compare_survival
  from sksurv.datasets import load_breast_cancer, load_veterans_lung_cancer
  from sksurv.nonparametric import kaplan_meier_estimator, nelson_aalen_estimator
  from sksurv.tree import SurvivalTree
  from sksurv.util import Surv
label_desc: Use image node_id 2 for calling the LogrankTreeBuilder obj's underlying member method code with example usage: obj.build(X, y) and returns: pd