code: def add_tag_trace(thing: T, user_line: Optional[int] = None) -> T:
      """Add tag.trace to a node or variable.
  
      The argument is returned after being affected (inplace).
  
      Parameters
      ----------
      thing
          The object where we add .tag.trace.
      user_line
          The max number of user line to keep.
  
      Notes
      -----
      We also use config.traceback__limit for the maximum number of stack level
      we look.
  
      """
      from pytensor.configdefaults import config
  
      if user_line is None:
          user_line = config.traceback__limit
  
      if user_line == -1:
          user_line = None
      skips = [
          "pytensor/tensor/",
          "pytensor\\tensor\\",
          "pytensor/compile/",
          "pytensor\\compile\\",
          "pytensor/graph/",
          "pytensor\\graph\\",
          "pytensor/scalar/basic.py",
          "pytensor\\scalar\\basic.py",
          "pytensor/sandbox/",
          "pytensor\\sandbox\\",
          "pytensor/scan/",
          "pytensor\\scan\\",
          "pytensor/sparse/",
          "pytensor\\sparse\\",
          "pytensor/typed_list/",
          "pytensor\\typed_list\\",
      ]
  
      if config.traceback__compile_limit > 0:
          skips = []
  
      tr = simple_extract_stack(limit=user_line, skips=skips)
      # Different python version use different sementic for
      # limit. python 2.7 include the call to extrack_stack. The -1 get
      # rid of it.
  
      if tr:
          thing.tag.trace = [tr]
      else:
          thing.tag.trace = tr
      return thing
  
imports: import linecache
  import sys
  import traceback
  from abc import ABCMeta
  from collections.abc import Sequence
  from io import StringIO
  from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
label_desc: Use image node_id 2 for calling a global function with example usage: add_tag_trace(thing, user_line) and returns: thing