docs: def _unwrap_maps(self, name_maps, name, study=None, **inner_maps):
          """
          Unwraps potentially nested name-mapping dictionaries to get values
          for name, input_map, output_map and study. Unsed in __init__.
  
          Parameters
          ----------
          name_maps : dict
              A dictionary containing the name_maps to apply to the values
          name : str
              Name passed from inner pipeline constructor
          study : Study
              The study to bind the pipeline to. Will be overridden by any values
              in the mods dict
          inner_maps : dict[str, dict[str,str]]
              input and output maps from inner pipeline constructors
  
          Returns
          -------
          name : str
              Potentially modified name of the pipeline
          study : Study
              Potentially modified study
          maps : dict[str, dict[str,str]]
              Potentially modifed input and output maps
          """
          # Set values of name and study
          name = name_maps.get('name', name)
          name = name_maps.get('prefix', '') + name
          study = name_maps.get('study', study)
          # Flatten input and output maps, combining maps from inner nests with
          # those in the "mods" dictionary
          maps = {}
          for mtype in ('input_map', 'output_map'):
              try:
                  inner_map = inner_maps[mtype]
              except KeyError:
                  try:
                      maps[mtype] = name_maps[mtype]  # Only outer map
                  except KeyError:
                      pass  # No maps
              else:
                  try:
                      outer_map = name_maps[mtype]
                  except KeyError:
                      maps[mtype] = inner_map  # Only inner map
                  else:
                      # Work through different combinations of  inner and outer
                      # map types (i.e. str & str, str & dict, dict & str, and
                      # dict & dict) and combine into a single map
                      if isinstance(outer_map, basestring):
                          if isinstance(inner_map, basestring):
                              # Concatenate prefixes
                              maps[mtype] = outer_map + inner_map
                          elif isinstance(inner_map, dict):
                              # Add outer_map prefix to all values in inner map
                              # dictionary
                              maps[mtype] = {k: outer_map + v
                                             for k, v in inner_map.items()}
                          else:
                              raise ArcanaDesignError(
                                  "Unrecognised type for name map in '{}' "
                                  "pipeline can be str or dict[str,str]: {}"
                                  .format(name, inner_map))
                      elif isinstance(outer_map, dict):
                          if isinstance(inner_map, basestring):
                              # Strip inner map prefix from outer dictionary
                              # (which should have prefix included). This should
                              # be an unlikely case I imagine
                              maps[mtype] = {k[len(inner_map):]: v
                                             for k, v in outer_map.items()}
                          elif isinstance(inner_map, dict):
                              # Chain outer_map dictionary to inner map
                              # dictionary
                              maps[mtype] = deepcopy(outer_map)
                              maps[mtype].update(
                                  {k: outer_map.get(v, v)
                                   for k, v in inner_map.items()})
                          else:
                              raise ArcanaDesignError(
                                  "Unrecognised type for name map in '{}' "
                                  "pipeline can be str or dict[str,str]: {}"
                                  .format(name, inner_map))
                      else:
                          raise ArcanaDesignError(
                              "Unrecognised type for name map in '{}' "
                              "pipeline can be str or dict[str,str]: {}"
                              .format(name, outer_map))
          try:
              outer_maps = name_maps['name_maps']
          except KeyError:
              pass
          else:
              name, study, maps = self._unwrap_maps(
                  outer_maps, name=name, study=study, **maps)
          return name, study, maps