parameters: (call_name, response)
docstring: Combine responses from different MPI processes.
  
      In a distributed scenario, each MPI process creates its own share
      of the response from the data available locally. To present a
      coherent view on the reponse data for the caller, this data has to
      be combined.
  
      If this function is run serially (i.e., without MPI), it just
      returns the response data from the only process immediately.
  
      The type of the returned result can vary depending on the call
      that produced it.
  
      The combination of results is based on a cascade of heuristics
      based on the call that was issued and individual repsonse data:
        * if all responses are None, the combined response will also just
          be None
        * for some specific calls, the responses are known to be the
          same from the master and all workers. In this case, the
          combined response is just the master response
        * if the response list contains only a single actual response and
          None otherwise, the combined response will be that one actual
          response
        * for calls to GetStatus on recording devices, the combined
          response will be a merged dictionary in the sense that all
          fields that contain a single value in the individual responsed
          are kept as a single values, while lists will be appended in
          order of appearance; dictionaries in the response are
          recursively treated in the same way
        * for calls to GetStatus on neurons, the combined response is just
          the single dictionary returned by the process on which the
          neuron is actually allocated
        * if the response contains one list per process, the combined
          response will be those lists concatenated and flattened.
docstring_summary: Combine responses from different MPI processes.
docstring_tokens: Combine responses from different MPI processes .
function: def combine(call_name, response):
      """Combine responses from different MPI processes.
  
      In a distributed scenario, each MPI process creates its own share
      of the response from the data available locally. To present a
      coherent view on the reponse data for the caller, this data has to
      be combined.
  
      If this function is run serially (i.e., without MPI), it just
      returns the response data from the only process immediately.
  
      The type of the returned result can vary depending on the call
      that produced it.
  
      The combination of results is based on a cascade of heuristics
      based on the call that was issued and individual repsonse data:
        * if all responses are None, the combined response will also just
          be None
        * for some specific calls, the responses are known to be the
          same from the master and all workers. In this case, the
          combined response is just the master response
        * if the response list contains only a single actual response and
          None otherwise, the combined response will be that one actual
          response
        * for calls to GetStatus on recording devices, the combined
          response will be a merged dictionary in the sense that all
          fields that contain a single value in the individual responsed
          are kept as a single values, while lists will be appended in
          order of appearance; dictionaries in the response are
          recursively treated in the same way
        * for calls to GetStatus on neurons, the combined response is just
          the single dictionary returned by the process on which the
          neuron is actually allocated
        * if the response contains one list per process, the combined
          response will be those lists concatenated and flattened.
  
      """
  
      if mpi_comm is None:
          return response[0]
  
      if all(v is None for v in response):
          return None
  
      # return the master response if all responses are known to be the same
      if call_name in ('exec', 'Create', 'GetDefaults', 'GetKernelStatus',
                       'SetKernelStatus', 'SetStatus'):
          return response[0]
  
      # return a single response if there is only one which is not None
      filtered_response = list(filter(lambda x: x is not None, response))
      if len(filtered_response) == 1:
          return filtered_response[0]
  
      # return a single merged dictionary if there are many of them
      if all(type(v[0]) is dict for v in response):
          return merge_dicts(response)
  
      # return a flattened list if the response only consists of lists
      if all(type(v) is list for v in response):
          return [item for lst in response for item in lst]
  
      log("combine()", f"ERROR: cannot combine response={response}")
      msg = "Cannot combine data because of unknown reason"
      raise Exception(msg)
function_tokens: def combine ( call_name , response ) : if mpi_comm is None : return response [ 0 ] if all ( v is None for v in response ) : return None # return the master response if all responses are known to be the same if call_name in ( 'exec' , 'Create' , 'GetDefaults' , 'GetKernelStatus' , 'SetKernelStatus' , 'SetStatus' ) : return response [ 0 ] # return a single response if there is only one which is not None filtered_response = list ( filter ( lambda x : x is not None , response ) ) if len ( filtered_response ) == 1 : return filtered_response [ 0 ] # return a single merged dictionary if there are many of them if all ( type ( v [ 0 ] ) is dict for v in response ) : return merge_dicts ( response ) # return a flattened list if the response only consists of lists if all ( type ( v ) is list for v in response ) : return [ item for lst in response for item in lst ] log ( "combine()" , f"ERROR: cannot combine response={response}" ) msg = "Cannot combine data because of unknown reason" raise Exception ( msg )