class_docstr: Recorder wrapper (specification key: `recorder`).
  
  Args:
      fn_act (callable[states -> actions]): Act-function mapping states to actions which is
          supposed to be recorded.
class_docstr_tok: ["Recorder","wrapper","(","specification","key",":","`","recorder","`",")",".","Args",":","fn_act","(","callable","[","states","-",">","actions","]",")",":","Act-function","mapping","states","to","actions","which","is","supposed","to","be","recorded","."]
code: def _process_states_input(self, states, function_name):
      if (
          self.states_spec.is_singleton()
          and not isinstance(states, dict)
          and not (
              util.is_iterable(x=states) and isinstance(states[0], dict)
          )
      ):
          # Single state
          states = np.asarray(states)
          if states.shape == self.states_spec.value().shape:
              # Single state is not batched
              states = ArrayDict(
                  singleton=np.expand_dims(states, axis=0)
              )
              batched = False
              num_instances = 1
              is_iter_of_dicts = None
  
          else:
              # Single state is batched, iter[state]
              assert states.shape[1:] == self.states_spec.value().shape
              assert type(states) in (tuple, list, np.ndarray)
              num_instances = states.shape[0]
              states = ArrayDict(singleton=states)
              batched = True
              is_iter_of_dicts = True  # Default
  
      elif util.is_iterable(x=states):
          # States is batched, iter[dict[state]]
          batched = True
          num_instances = len(states)
          is_iter_of_dicts = True
          assert type(states) in (tuple, list)
          if num_instances == 0:
              raise TensorforceError.value(
                  name=function_name,
                  argument="len(states)",
                  value=num_instances,
                  hint="= 0",
              )
          for n, state in enumerate(states):
              if not isinstance(state, dict):
                  raise TensorforceError.type(
                      name=function_name,
                      argument="states[{}]".format(n),
                      dtype=type(state),
                      hint="is not dict",
                  )
          # Turn iter of dicts into dict of arrays
          # (Doesn't use self.states_spec since states also contains auxiliaries)
          states = [ArrayDict(state) for state in states]
          states = states[0].fmap(
              function=(lambda *xs: np.stack(xs, axis=0)),
              zip_values=states[1:],
          )
  
      elif isinstance(states, dict):
          # States is dict, turn into arrays
          states = ArrayDict(states)
          name, spec = self.states_spec.item()
          if name is None:
              name = "state"
  
          if states[name].shape == spec.shape:
              # States is not batched, dict[state]
              states = states.fmap(
                  function=(lambda state: np.expand_dims(state, axis=0))
              )
              batched = False
              num_instances = 1
              is_iter_of_dicts = None
  
          else:
              # States is batched, dict[iter[state]]
              assert states[name].shape[1:] == spec.shape
              assert type(states[name]) in (tuple, list, np.ndarray)
              batched = True
              num_instances = states[name].shape[0]
              is_iter_of_dicts = False
              if num_instances == 0:
                  raise TensorforceError.value(
                      name=function_name,
                      argument="len(states)",
                      value=num_instances,
                      hint="= 0",
                  )
  
      else:
          raise TensorforceError.type(
              name=function_name,
              argument="states",
              dtype=type(states),
              hint="is not array/tuple/list/dict",
          )
  
      # Check number of inputs
      if any(
          state.shape[0] != num_instances for state in states.values()
      ):
          raise TensorforceError.value(
              name=function_name,
              argument="len(states)",
              value=[state.shape[0] for state in states.values()],
              hint="inconsistent",
          )
  
      return states, batched, num_instances, is_iter_of_dicts
  
file_path: tensorforce/tensorforce/agents/recorder.py
imports: import os
  from collections import OrderedDict
  import numpy
  from tensorforce import TensorforceError, util
  from tensorforce.core import ArrayDict, ListDict, TensorSpec, TensorsSpec
label_desc: Use image node_id 8 for calling the Recorder obj's underlying member method code with example usage: obj._process_states_input(states, function_name) and returns: states,  batched,  num_instances,  is_iter_of_dicts