class_docstr: Stores multi-agent episode data.
  
  The central attribute of the class is the timestep mapping
  `global_t_to_local_t` that maps the global (environment)
  timestep to the local (agent) timesteps.
  
  The `MultiAgentEpisode` is based on the `SingleAgentEpisode`s
  for each agent, stored in `MultiAgentEpisode.agent_episodes`.
class_docstr_tok: ["Stores","multi-agent","episode","data",".","The","central","attribute","of","the","class","is","the","timestep","mapping","`","global_t_to_local_t","`","that","maps","the","global","(","environment",")","timestep","to","the","local","(","agent",")","timesteps",".","The","`","MultiAgentEpisode","`","is","based","on","the","`","SingleAgentEpisode","`","s","for","each","agent",",","stored","in","`","MultiAgentEpisode.agent_episodes","`","."]
docstr: Gets actions for all agents that stepped in the last timesteps.
  
  Note that actions are only returned for agents that stepped
  during the given index range.
  
  Args:
      key: A string determining the key in the extra model outputs
          dictionary to return. This parameter is mandatory.
      indices: Either a single index or a list of indices. The indices
          can be reversed (e.g. [-1, -2]) or absolute (e.g. [98, 99]).
          This defines the time indices for which the actions
          should be returned.
      global_ts: Boolean that defines, if the indices should be considered
          environment (`True`) or agent (`False`) steps.
  
  Returns: A dictionary mapping agent ids to actions (of different
      timesteps). Only for agents that have stepped (were ready) at a
      timestep, actions are returned (i.e. not all agent ids are
      necessarily in the keys).
code: def get_extra_model_outputs(
      self,
      key: str,
      indices: Union[int, List[int]] = -1,
      global_ts: bool = True,
      as_list: bool = False,
  ) -> Union[MultiAgentDict, List[MultiAgentDict]]:
      """Gets actions for all agents that stepped in the last timesteps.
  
      Note that actions are only returned for agents that stepped
      during the given index range.
  
      Args:
          key: A string determining the key in the extra model outputs
              dictionary to return. This parameter is mandatory.
          indices: Either a single index or a list of indices. The indices
              can be reversed (e.g. [-1, -2]) or absolute (e.g. [98, 99]).
              This defines the time indices for which the actions
              should be returned.
          global_ts: Boolean that defines, if the indices should be considered
              environment (`True`) or agent (`False`) steps.
  
      Returns: A dictionary mapping agent ids to actions (of different
          timesteps). Only for agents that have stepped (were ready) at a
          timestep, actions are returned (i.e. not all agent ids are
          necessarily in the keys).
      """
      assert (
          key
      ), "ERROR: When requesting extra model outputs a `key` is needed."
      buffered_outputs = {}
  
      if global_ts:
          # Check, if the indices are iterable.
          if isinstance(indices, list):
              indices = [
                  (self.t + idx + 1 if idx < 0 else idx)
                  for idx in indices
              ]
          # If not make them iterable.
          else:
              indices = (
                  [self.t + indices + 1] if indices < 0 else [indices]
              )
      else:
          if not isinstance(indices, list):
              indices = [indices]
      # Check now, if one of these indices is the last in the global
      # action timestep mapping.
      for (
          agent_id,
          agent_global_action_t,
      ) in self.global_actions_t.items():
          if agent_global_action_t:
              last_action_index = (
                  agent_global_action_t[-1]
                  if global_ts
                  else len(agent_global_action_t) - 1
              )
          # We consider only timesteps that are in the requested indices and
          # check then, if for these the buffer is full. Note, we cannot use
          # the extra model outputs buffer as this is by default `None`.
          if (
              agent_global_action_t
              and (last_action_index in indices or -1 in indices)
              and self.agent_buffers[agent_id]["actions"].full()
          ):
              # Then the buffer must be full and needs to be accessed.
              # Note, we do not want to empty the buffer, but only read it.
              buffered_outputs[agent_id] = [
                  self.agent_buffers[agent_id][
                      "extra_model_outputs"
                  ].queue[0][key]
              ]
  
          else:
              buffered_outputs[agent_id] = []
  
      # Now, get the actions.
      extra_model_outputs = self._getattr_by_index(
          "extra_model_outputs",
          indices=indices,
          key=key,
          has_initial_value=True,
          global_ts=global_ts,
          global_ts_mapping=self.global_actions_t,
          # shift=1,
          as_list=as_list,
          buffered_values=buffered_outputs,
      )
  
      return extra_model_outputs
  
imports: from collections import defaultdict
  from queue import Queue
  from typing import Any, Dict, List, Optional, Set, Union
  import uuid
  import numpy
  from ray.rllib.env.single_agent_episode import SingleAgentEpisode
  from ray.rllib.policy.sample_batch import MultiAgentBatch
  from ray.rllib.utils.typing import MultiAgentDict
label_desc: Use image node_id 5 for calling the MultiAgentEpisode obj's underlying member method code with example usage: obj.get_extra_model_outputs(key, indices, global_ts, as_list) and returns: extra_model_outputs