code: def _get_nodes_info(self, tree_model):
      tree_nodes = [None] * tree_model.numNodes
      children_left = [-1] * tree_model.numNodes
      children_right = [-1] * tree_model.numNodes
      node_index = 0
  
      def recur(node, node_id):
          nonlocal node_index
          tree_nodes[node_id] = node
          if node.numDescendants() == 0:
              return
          else:
              node_index += 1
              children_left[node_id] = node_index
              recur(node.leftChild(), node_index)
  
              node_index += 1
              children_right[node_id] = node_index
              recur(node.rightChild(), node_index)
  
      recur(tree_model._call_java("rootNode"), 0)
      return tree_nodes, children_left, children_right
  
imports: from abc import ABC
  from collections import defaultdict
  from typing import List, Mapping
  import numpy
  import pyspark
  from dtreeviz.models.shadow_decision_tree import ShadowDecTree
  from dtreeviz.utils import criterion_remapping
  from pyspark.ml.classification import DecisionTreeClassificationModel
  from pyspark.ml.regression import DecisionTreeRegressionModel
label_desc: Use image node_id 2 for calling the ShadowSparkTree obj's underlying member method code with example usage: obj._get_nodes_info(tree_model) and returns: tree_nodes,  children_left,  children_right