code: def particle_filter(
      observations,
      initial_state_prior,
      transition_fn,
      observation_fn,
      num_particles,
      initial_state_proposal=None,
      proposal_fn=None,
      resample_fn=weighted_resampling.resample_systematic,
      resample_criterion_fn=smc_kernel.ess_below_threshold,
      unbiased_gradients=True,
      rejuvenation_kernel_fn=None,  # TODO(davmre): not yet supported. pylint: disable=unused-argument
      num_transitions_per_observation=1,
      particles_dim=0,
      trace_fn=_default_trace_fn,
      trace_criterion_fn=_always_trace,
      static_trace_allocation_size=None,
      parallel_iterations=1,
      seed=None,
      name=None,
  ):  # pylint: disable=g-doc-args
      """Samples a series of particles representing filtered latent states.
  
      The particle filter samples from the sequence of "filtering" distributions
      `p(state[t] | observations[:t])` over latent
      states: at each point in time, this is the distribution conditioned on all
      observations *up to that time*. Because particles may be resampled, a
      particle at time `t` may be different from the particle with the same index
      at time `t + 1`. To reconstruct trajectories by tracing back through the
      resampling process, see `tfp.mcmc.experimental.reconstruct_trajectories`.
  
      ${particle_filter_arg_str}
        trace_fn: Python `callable` defining the values to be traced at each step,
          with signature `traced_values = trace_fn(weighted_particles, results)`
          in which the first argument is an instance of
          `tfp.experimental.mcmc.WeightedParticles` and the second an instance of
          `SequentialMonteCarloResults` tuple, and the return value is a structure
          of `Tensor`s.
          Default value: `lambda s, r: (s.particles, s.log_weights,
          r.parent_indices, r.incremental_log_marginal_likelihood)`
        trace_criterion_fn: optional Python `callable` with signature
          `trace_this_step = trace_criterion_fn(weighted_particles, results)` taking
          the same arguments as `trace_fn` and returning a boolean `Tensor`. If
          `None`, only values from the final step are returned.
          Default value: `lambda *_: True` (trace every step).
        static_trace_allocation_size: Optional Python `int` size of trace to
          allocate statically. This should be an upper bound on the number of steps
          traced and is used only when the length cannot be
          statically inferred (for example, if a `trace_criterion_fn` is specified).
          It is primarily intended for contexts where static shapes are required,
          such as in XLA-compiled code.
          Default value: `None`.
        parallel_iterations: Passed to the internal `tf.while_loop`.
          Default value: `1`.
        seed: PRNG seed; see `tfp.random.sanitize_seed` for details.
        name: Python `str` name for ops created by this method.
          Default value: `None` (i.e., `'particle_filter'`).
      Returns:
        traced_results: A structure of Tensors as returned by `trace_fn`. If
          `trace_criterion_fn==None`, this is computed from the final step;
          otherwise, each Tensor will have initial dimension `num_steps_traced`
          and stacks the traced results across all steps.
  
      #### References
  
      [1] Adam Scibior, Vaden Masrani, and Frank Wood. Differentiable Particle
          Filtering without Modifying the Forward Pass. _arXiv preprint
          arXiv:2106.10314_, 2021. https://arxiv.org/abs/2106.10314
      """
  
      init_seed, loop_seed = samplers.split_seed(
          seed, salt="particle_filter"
      )
      with tf.name_scope(name or "particle_filter"):
          num_observation_steps = ps.size0(
              tf.nest.flatten(observations)[0]
          )
          num_timesteps = 1 + num_transitions_per_observation * (
              num_observation_steps - 1
          )
  
          initial_weighted_particles = (
              _particle_filter_initial_weighted_particles(
                  observations=observations,
                  observation_fn=observation_fn,
                  initial_state_prior=initial_state_prior,
                  initial_state_proposal=initial_state_proposal,
                  num_particles=num_particles,
                  particles_dim=particles_dim,
                  seed=init_seed,
              )
          )
          propose_and_update_log_weights_fn = _particle_filter_propose_and_update_log_weights_fn(
              observations=observations,
              transition_fn=transition_fn,
              particles_dim=particles_dim,
              proposal_fn=proposal_fn,
              observation_fn=observation_fn,
              num_transitions_per_observation=num_transitions_per_observation,
          )
  
          return sequential_monte_carlo(
              initial_weighted_particles=initial_weighted_particles,
              num_steps=num_timesteps,
              parallel_iterations=parallel_iterations,
              particles_dim=particles_dim,
              propose_and_update_log_weights_fn=propose_and_update_log_weights_fn,
              resample_fn=resample_fn,
              resample_criterion_fn=resample_criterion_fn,
              static_trace_allocation_size=static_trace_allocation_size,
              trace_criterion_fn=trace_criterion_fn,
              trace_fn=trace_fn,
              unbiased_gradients=unbiased_gradients,
              seed=loop_seed,
          )
  
file_path: probability/tensorflow_probability/python/experimental/mcmc/particle_filter.py
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.experimental.mcmc import sequential_monte_carlo_kernel
  from tensorflow_probability.python.experimental.mcmc import weighted_resampling
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import docstring_util
  from tensorflow_probability.python.internal import loop_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.mcmc.internal import util
label_desc: Use image node_id 4 for calling a global function with example usage: particle_filter(observations, initial_state_prior, transition_fn, observation_fn, num_particles, initial_state_proposal, proposal_fn, resample_fn, resample_criterion_fn, unbiased_gradients, rejuvenation_kernel_fn, num_transitions_per_observation, particles_dim, trace_fn, trace_criterion_fn, static_trace_allocation_size, parallel_iterations, seed, name) and returns: sequential_monte_carlo