code: def sample(
      name: str,
      fn: TorchDistributionMixin,
      *args,
      obs: Optional[torch.Tensor] = None,
      obs_mask: Optional[torch.Tensor] = None,
      infer: Optional[InferDict] = None,
      **kwargs,
  ) -> torch.Tensor:
      """
      Calls the stochastic function ``fn`` with additional side-effects depending
      on ``name`` and the enclosing context (e.g. an inference algorithm).  See
      `Introduction to Pyro <http://pyro.ai/examples/intro_long.html>`_ for a discussion.
  
      :param name: name of sample
      :param fn: distribution class or function
      :param obs: observed datum (optional; should only be used in context of
          inference) optionally specified in kwargs
      :param ~torch.Tensor obs_mask: Optional boolean tensor mask of shape
          broadcastable with ``fn.batch_shape``. If provided, events with
          mask=True will be conditioned on ``obs`` and remaining events will be
          imputed by sampling. This introduces a latent sample site named ``name
          + "_unobserved"`` which should be used by guides.
      :type obs_mask: bool or ~torch.Tensor
      :param dict infer: Optional dictionary of inference parameters specified
          in kwargs. See inference documentation for details.
      :returns: sample
      """
      # Transform obs_mask into multiple sample statements.
      if obs_mask is not None:
          return _masked_observe(
              name, fn, obs, obs_mask, *args, **kwargs
          )
  
      # Check if stack is empty.
      # if stack empty, default behavior (defined here)
      infer = {} if infer is None else infer.copy()
      is_observed = infer.pop("is_observed", obs is not None)
      assert isinstance(is_observed, bool)
      if not am_i_wrapped():
          if obs is not None and not infer.get("_deterministic"):
              warnings.warn(
                  "trying to observe a value outside of inference at "
                  + name,
                  RuntimeWarning,
              )
              return obs
          return fn(*args, **kwargs)
      # if stack not empty, apply everything in the stack?
      else:
          # initialize data structure to pass up/down the stack
          msg = Message(
              type="sample",
              name=name,
              fn=fn,
              is_observed=is_observed,
              args=args,
              kwargs=kwargs,
              value=obs,
              infer=infer,
              scale=1.0,
              mask=None,
              cond_indep_stack=(),
              done=False,
              stop=False,
              continuation=None,
          )
          # apply the stack and return its return value
          apply_stack(msg)
          assert (
              msg["value"] is not None
          )  # type narrowing guaranteed by apply_stack
          return msg["value"]
  
imports: import copy
  import warnings
  from collections import OrderedDict
  from contextlib import ExitStack, contextmanager
  from inspect import isclass
  from typing import Callable, Iterator, Optional, Sequence, Union
  import torch
  from torch.distributions import constraints
  import pyro.distributions
  import pyro.infer
  import pyro.poutine
  from pyro.distributions.torch_distribution import TorchDistributionMixin
  from pyro.params import param_with_module_name
  from pyro.params.param_store import ParamStoreDict
  from pyro.poutine.plate_messenger import PlateMessenger
  from pyro.poutine.runtime import _MODULE_NAMESPACE_DIVIDER, _PYRO_PARAM_STORE, InferDict, Message, am_i_wrapped, apply_stack, effectful
  from pyro.poutine.subsample_messenger import SubsampleMessenger
  from pyro.util import deep_getattr, set_rng_seed
label_desc: Use image node_id 5 for calling a global function with example usage: sample(name, fn) and returns: _masked_observe, fn, msg, obs