code: def _guest_split(
      self,
      ctx: Context,
      stat_rs,
      cur_layer_node,
      node_map,
      sk,
      coder,
      gh_pack,
      pack_info,
  ):
      if sk is None or coder is None:
          raise ValueError(
              "sk or coder is None, not able to decode host split points"
          )
  
      histogram = stat_rs.decrypt({}, {}, None)
      sitename = ctx.local.name
      reverse_node_map = {v: k for k, v in node_map.items()}
  
      # find local best splits
      guest_best_splits = self._find_best_splits(
          histogram,
          sitename,
          cur_layer_node,
          reverse_node_map,
          recover_bucket=True,
      )
      # find best splits from host parties
      host_histograms = ctx.hosts.get("hist")
  
      host_splits = []
      if gh_pack:
          decrypt_schema = ({"gh": sk}, {"gh": (coder, torch.int64)})
          # (coder, pack_num, offset_bit, precision, total_num)
          if pack_info is not None:
              decode_schema = {
                  "gh": (
                      coder,
                      pack_info["pack_num"],
                      pack_info["shift_bit"],
                      pack_info["precision"],
                      pack_info["total_pack_num"],
                  )
              }
          else:
              raise ValueError("pack info is not provided")
      else:
          decrypt_schema = (
              {"g": sk, "h": sk},
              {
                  "g": (coder, torch.float32),
                  "h": (coder, torch.float32),
              },
          )
          decode_schema = None
  
      for idx, hist in enumerate(host_histograms):
          host_sitename = ctx.hosts[idx].name
          host_hist = self._recover_pack_split(
              hist, decrypt_schema, decode_schema
          )
          # logger.debug("splitting host")
          host_split = self._find_best_splits(
              host_hist,
              host_sitename,
              cur_layer_node,
              reverse_node_map,
              recover_bucket=False,
              pack_info=pack_info,
          )
          host_splits.append(host_split)
  
      # logger.debug("host splits are {}".format(host_splits))
      best_splits = self._merge_splits(guest_best_splits, host_splits)
      # logger.debug("guest splits are {}".format(guest_best_splits))
      # logger.debug("best splits are {}".format(best_splits))
      return best_splits
  
imports: import torch
  import numpy
  import logging
  from fate.arch.dataframe import DataFrame
  from fate.arch import Context
  from fate.arch.histogram import DistributedHistogram
label_desc: Use image node_id 15 for calling the SBTSplitter obj's underlying member method code with example usage: obj._guest_split(ctx, stat_rs, cur_layer_node, node_map, sk, coder, gh_pack, pack_info) and returns: best_splits