class_docstr: Tracks the current if/else scope with the path that we took. Captures the used and produced
  data nodes, applying the necessary splits based on the scope level where they were produced
  and where they are used.
docstr: Return the DataNode that can be used as a reference batch size in this scope.
  None is returned if we are in the top level scope.
docstr_tok: ["Return","the","DataNode","that","can","be","used","as","a","reference","batch","size","in","this","scope",".","None","is","returned","if","we","are","in","the","top","level","scope","."]
code: def scope_batch_size_tracker(self):
      """Return the DataNode that can be used as a reference batch size in this scope.
      None is returned if we are in the top level scope.
      """
      if self.stack_depth() == 1:
          return None
      if self.top().branch in {_Branch.TrueBranch, _Branch.FalseBranch}:
          # In worst case we will introduce a split on the predicate itself, but we know,
          # we can consistently do it, and it will happen only for the first operator call,
          # for the following ones in this scope it will be cached.
          return self.preprocess_input(self.top().predicate)
      else:
          # If we are in the merge stage, just use the size of the predicate
          return self.top().predicate
  
imports: from nvidia.dali import _autograph
  from nvidia.dali.data_node import DataNode
  from nvidia.dali import fn
  from nvidia.dali._autograph.utils import ag_logging
  from nvidia.dali._autograph.operators import variables
  from contextlib import contextmanager
  from enum import Enum
  import tree
label_desc: Use image node_id 14 for calling the _ConditionStack obj's underlying member method code with example usage: obj.scope_batch_size_tracker() and returns: None, self, self