code: def plink_merge(
      b: Batch,
      bfiles: List[ResourceGroup],
      image: Optional[str] = None,
      branching_factor: int = 100,
  ) -> ResourceGroup:
      """
      Merge binary PLINK files using tree aggregation.
  
      Parameters
      ----------
      b:
          Batch to add merge jobs to.
      bfiles:
          List of binary PLINK file roots to merge.
      image:
          Image name that contains PLINK.
      branching_factor:
          Grouping factor when merging files.
  
      Returns
      -------
      Merged binary PLINK file.
      """
  
      def _plink_merge(b, name, xs):
          assert xs
          if len(xs) == 1:
              return xs[0]
          j = b.new_job(name=name)
          if image:
              j.image(image)
          for f in xs[1:]:
              j.command(f'echo "{f.bed} {f.bim} {f.fam}" >> merge_list')
          j.command(
              f"plink --bfile {xs[0]} --merge-list merge_list --out {j.ofile}"
          )
          return j.ofile
  
      if len(bfiles) == 0:
          raise BatchException(
              "Must have at least one binary PLINK file to merge."
          )
  
      if not all(isinstance(bf, ResourceGroup) for bf in bfiles):
          raise BatchException(
              "Invalid input file(s) - all inputs must be resource groups."
          )
  
      return _combine(
          _plink_merge,
          b,
          "plink-merge",
          bfiles,
          branching_factor=branching_factor,
      )
  
file_path: hail/hail/python/hailtop/batch/utils.py
imports: import math
  from typing import List, Optional
  from ..utils.utils import grouped, digits_needed
  from .batch import Batch
  from .exceptions import BatchException
  from .resource import ResourceGroup, ResourceFile
label_desc: Use image node_id 2 for calling a global function with example usage: plink_merge(b, bfiles, image, branching_factor) and returns: _combine, j, xs