code: def _update_tree(
      self,
      ctx: Context,
      cur_layer_nodes: List[Node],
      split_info: List[SplitInfo],
      data: DataFrame,
  ) -> object:
      assert len(cur_layer_nodes) == len(
          split_info
      ), "node num not match split info num, got {} node vs {} split info".format(
          len(cur_layer_nodes), len(split_info)
      )
  
      next_layer_node = []
  
      for idx in range(len(split_info)):
          node: Node = cur_layer_nodes[idx]
  
          if split_info[idx] is None:
              node.is_leaf = True
              node.sitename = (
                  ctx.guest.name
              )  # leaf always belongs to guest
              self._nodes.append(node)
              continue
  
          sum_grad = node.grad
          sum_hess = node.hess
          sum_cnt = node.sample_num
  
          feat_name = self._fid_to_feature_name(
              split_info[idx].best_fid, data
          )
          node.fid = feat_name
          node.bid = split_info[idx].best_bid
          node.missing_dir = split_info[idx].missing_dir
          node.sitename = split_info[idx].sitename
          node.split_id = split_info[
              idx
          ].split_id  # if not a local node, has split id
  
          p_id = node.nid
          l_id, r_id = self._tree_node_num + 1, self._tree_node_num + 2
          self._tree_node_num += 2
          node.l, node.r = l_id, r_id
  
          l_g, l_h = split_info[idx].sum_grad, split_info[idx].sum_hess
          l_cnt = split_info[idx].sample_count
  
          # logger.info("splitting node {}, split info is {}".format(node, split_info[idx]))
  
          # create new left node and new right node
          left_node = Node(
              nid=l_id,
              grad=float(l_g),
              hess=float(l_h),
              weight=float(self.splitter.node_weight(l_g, l_h)),
              parent_nodeid=p_id,
              sibling_nodeid=r_id,
              is_left_node=True,
              sample_num=l_cnt,
          )
  
          # this is not going to happen
          assert (
              sum_cnt > l_cnt
          ), "sum cnt {} not greater than l cnt {}".format(
              sum_cnt, l_cnt
          )
  
          r_g = float(sum_grad - l_g)
          r_h = float(sum_hess - l_h)
          r_cnt = sum_cnt - l_cnt
  
          right_node = Node(
              nid=r_id,
              grad=r_g,
              hess=r_h,
              weight=float(
                  self.splitter.node_weight(
                      sum_grad - l_g, sum_hess - l_h
                  )
              ),
              parent_nodeid=p_id,
              sibling_nodeid=l_id,
              sample_num=r_cnt,
              is_left_node=False,
          )
  
          next_layer_node.append(left_node)
          next_layer_node.append(right_node)
          self._nodes.append(node)
  
      return next_layer_node
  
imports: import numpy
  import pandas
  from fate.arch import Context
  from fate.arch.dataframe import DataFrame
  from fate.ml.ensemble.learner.decision_tree.tree_core.splitter import SplitInfo
  from typing import List
  import logging
label_desc: Use image node_id 10 for calling the DecisionTree obj's underlying member method code with example usage: obj._update_tree(ctx, cur_layer_nodes, split_info, data) and returns: next_layer_node