code: def sample_action(
      q_pi,
      policies,
      num_controls,
      action_selection="deterministic",
      alpha=16.0,
  ):
      """
      Computes the marginal posterior over actions and then samples an action from it, one action per control factor.
  
      Parameters
      ----------
      q_pi: 1D ``numpy.ndarray``
          Posterior beliefs over policies, i.e. a vector containing one posterior probability per policy.
      policies: ``list`` of 2D ``numpy.ndarray``
          ``list`` that stores each policy as a 2D array in ``policies[p_idx]``. Shape of ``policies[p_idx]``
          is ``(num_timesteps, num_factors)`` where ``num_timesteps`` is the temporal
          depth of the policy and ``num_factors`` is the number of control factors.
      num_controls: ``list`` of ``int``
          ``list`` of the dimensionalities of each control state factor.
      action_selection: ``str``, default "deterministic"
          String indicating whether whether the selected action is chosen as the maximum of the posterior over actions,
          or whether it's sampled from the posterior marginal over actions
      alpha: ``float``, default 16.0
          Action selection precision -- the inverse temperature of the softmax that is used to scale the
          action marginals before sampling. This is only used if ``action_selection`` argument is "stochastic"
  
      Returns
      ----------
      selected_policy: 1D ``numpy.ndarray``
          Vector containing the indices of the actions for each control factor
      """
  
      num_factors = len(num_controls)
  
      action_marginals = utils.obj_array_zeros(num_controls)
  
      # weight each action according to its integrated posterior probability under all policies at the current timestep
      for pol_idx, policy in enumerate(policies):
          for factor_i, action_i in enumerate(policy[0, :]):
              action_marginals[factor_i][action_i] += q_pi[pol_idx]
  
      action_marginals = utils.norm_dist_obj_arr(action_marginals)
  
      selected_policy = np.zeros(num_factors)
      for factor_i in range(num_factors):
          # Either you do this:
          if action_selection == "deterministic":
              selected_policy[factor_i] = select_highest(
                  action_marginals[factor_i]
              )
          elif action_selection == "stochastic":
              log_marginal_f = spm_log_single(
                  action_marginals[factor_i]
              )
              p_actions = softmax(log_marginal_f * alpha)
              selected_policy[factor_i] = utils.sample(p_actions)
  
      return selected_policy
  
imports: import itertools
  import numpy
  from pymdp.maths import softmax, softmax_obj_arr, spm_dot, spm_wnorm, spm_MDP_G, spm_log_single, spm_log_obj_array
  from pymdp import utils
  import copy
label_desc: Use image node_id 11 for calling a global function with example usage: sample_action(q_pi, policies, num_controls, action_selection, alpha) and returns: selected_policy