code: def analyze_rnn_batch(batch, max_seq_len, view_requirements):
      count = batch.count
  
      # Check prev_reward/action, next_obs consistency.
      for idx in range(count):
          # If timestep tracked by batch, good.
          if "t" in batch:
              ts = batch["t"][idx]
          # Else, ts
          else:
              ts = batch[SampleBatch.OBS][idx][3]
          obs_t = batch[SampleBatch.OBS][idx]
          a_t = batch[SampleBatch.ACTIONS][idx]
          r_t = batch[SampleBatch.REWARDS][idx]
          state_in_0 = batch["state_in_0"][idx]
          state_in_1 = batch["state_in_1"][idx]
  
          # Check postprocessing outputs.
          if "2xobs" in batch:
              postprocessed_col_t = batch["2xobs"][idx]
              assert (obs_t == postprocessed_col_t / 2.0).all()
  
          # Check state-in/out and next-obs values.
          if idx > 0:
              next_obs_t_m_1 = batch[SampleBatch.NEXT_OBS][idx - 1]
              state_out_0_t_m_1 = batch["state_out_0"][idx - 1]
              state_out_1_t_m_1 = batch["state_out_1"][idx - 1]
              # Same trajectory as for t-1 -> Should be able to match.
              if (
                  batch[SampleBatch.AGENT_INDEX][idx]
                  == batch[SampleBatch.AGENT_INDEX][idx - 1]
                  and batch[SampleBatch.EPS_ID][idx]
                  == batch[SampleBatch.EPS_ID][idx - 1]
              ):
                  assert (
                      batch["unroll_id"][idx - 1]
                      == batch["unroll_id"][idx]
                  )
                  assert (obs_t == next_obs_t_m_1).all()
                  assert (state_in_0 == state_out_0_t_m_1).all()
                  assert (state_in_1 == state_out_1_t_m_1).all()
              # Different trajectory.
              else:
                  assert (
                      batch["unroll_id"][idx - 1]
                      != batch["unroll_id"][idx]
                  )
                  assert not (obs_t == next_obs_t_m_1).all()
                  assert not (state_in_0 == state_out_0_t_m_1).all()
                  assert not (state_in_1 == state_out_1_t_m_1).all()
                  # Check initial 0-internal states.
                  if ts == 0:
                      assert (state_in_0 == 0.0).all()
                      assert (state_in_1 == 0.0).all()
  
          # Check initial 0-internal states (at ts=0).
          if ts == 0:
              assert (state_in_0 == 0.0).all()
              assert (state_in_1 == 0.0).all()
  
          # Check prev. a/r values.
          if idx < count - 1:
              prev_actions_t_p_1 = batch[SampleBatch.PREV_ACTIONS][
                  idx + 1
              ]
              prev_rewards_t_p_1 = batch[SampleBatch.PREV_REWARDS][
                  idx + 1
              ]
              # Same trajectory as for t+1 -> Should be able to match.
              if (
                  batch[SampleBatch.AGENT_INDEX][idx]
                  == batch[SampleBatch.AGENT_INDEX][idx + 1]
                  and batch[SampleBatch.EPS_ID][idx]
                  == batch[SampleBatch.EPS_ID][idx + 1]
              ):
                  assert (a_t == prev_actions_t_p_1).all()
                  assert r_t == prev_rewards_t_p_1
              # Different (new) trajectory. Assume t-1 (prev-a/r) to be
              # always 0.0s. [3]=ts
              elif ts == 0:
                  assert (prev_actions_t_p_1 == 0).all()
                  assert prev_rewards_t_p_1 == 0.0
  
      pad_batch_to_sequences_of_same_size(
          batch,
          max_seq_len=max_seq_len,
          shuffle=False,
          batch_divisibility_req=1,
          view_requirements=view_requirements,
      )
  
      # Check after seq-len 0-padding.
      cursor = 0
      for i, seq_len in enumerate(batch[SampleBatch.SEQ_LENS]):
          state_in_0 = batch["state_in_0"][i]
          state_in_1 = batch["state_in_1"][i]
          for j in range(seq_len):
              k = cursor + j
              ts = batch[SampleBatch.T][k]
              obs_t = batch[SampleBatch.OBS][k]
              a_t = batch[SampleBatch.ACTIONS][k]
              r_t = batch[SampleBatch.REWARDS][k]
  
              # Check postprocessing outputs.
              if "2xobs" in batch:
                  postprocessed_col_t = batch["2xobs"][k]
                  assert (obs_t == postprocessed_col_t / 2.0).all()
  
              # Check state-in/out and next-obs values.
              if j > 0:
                  next_obs_t_m_1 = batch[SampleBatch.NEXT_OBS][k - 1]
                  # state_out_0_t_m_1 = batch["state_out_0"][k - 1]
                  # state_out_1_t_m_1 = batch["state_out_1"][k - 1]
                  # Always same trajectory as for t-1.
                  assert (
                      batch["unroll_id"][k - 1] == batch["unroll_id"][k]
                  )
                  assert (obs_t == next_obs_t_m_1).all()
                  # assert (state_in_0 == state_out_0_t_m_1).all())
                  # assert (state_in_1 == state_out_1_t_m_1).all())
              # Check initial 0-internal states.
              elif ts == 0:
                  assert (state_in_0 == 0.0).all()
                  assert (state_in_1 == 0.0).all()
  
          for j in range(seq_len, max_seq_len):
              k = cursor + j
              obs_t = batch[SampleBatch.OBS][k]
              a_t = batch[SampleBatch.ACTIONS][k]
              r_t = batch[SampleBatch.REWARDS][k]
              assert (obs_t == 0.0).all()
              assert (a_t == 0.0).all()
              assert (r_t == 0.0).all()
  
          cursor += max_seq_len
  
imports: import gymnasium
  from gymnasium.spaces import Box, Discrete
  import numpy
  import unittest
  import ray
  from ray.rllib.algorithms.callbacks import DefaultCallbacks
  import ray.rllib.algorithms.dqn
  import ray.rllib.algorithms.ppo
  from ray.rllib.examples.env.debug_counter_env import MultiAgentDebugCounterEnv
  from ray.rllib.examples.env.multi_agent import MultiAgentPendulum
  from ray.rllib.evaluation.rollout_worker import RolloutWorker
  from ray.rllib.examples.policy.episode_env_aware_policy import EpisodeEnvAwareAttentionPolicy, StatefulRandomPolicy
  from ray.rllib.models.tf.attention_net import GTrXLNet
  from ray.rllib.policy.rnn_sequencing import pad_batch_to_sequences_of_same_size
  from ray.rllib.policy.sample_batch import DEFAULT_POLICY_ID, SampleBatch, convert_ma_batch_to_sample_batch
  from ray.rllib.policy.view_requirement import ViewRequirement
  from ray.rllib.utils.annotations import override
  from ray.rllib.utils.test_utils import framework_iterator, check
label_desc: Use image node_id 1 for calling a global function with example usage: analyze_rnn_batch(batch, max_seq_len, view_requirements) without return types