def Func(arg_0, arg_1, arg_2):
        """Stores original data type to hdf5 node attributes for preserving the data type.

        :param data:

            Data to be stored

        :param ptitem:

            HDF5 node to store data types as attributes. Can also be just a PTItemMock.

        :param prefix:

            String prefix to label and name data in HDF5 attributes

        """

        # If `data` is a container, remember the container type
        if type(arg_0) is tuple:
            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_TUPLE)

        elif type(arg_0) is list:
            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_LIST)

        elif type(arg_0) is np.ndarray:
            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_NDARRAY)

        elif type(arg_0) is np.matrix:
            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_MATRIX)

        elif type(arg_0) in pypetconstants.PARAMETER_SUPPORTED_DATA:
            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_SCALAR)

            arg_3 = type(arg_0).__name__

            if not arg_3 in pypetconstants.PARAMETERTYPEDICT:
                raise TypeError('I do not know how to handle `%s` its type is `%s`.' %
                                (str(arg_0), repr(type(arg_0))))

            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.SCALAR_TYPE, arg_3)

        elif type(arg_0) is dict:
            if len(arg_0) > 0:
                HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_DICT)
            else:
                HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.COLL_TYPE,
                                   HDF5StorageService.COLL_EMPTY_DICT)
        else:
            raise TypeError('I do not know how to handle `%s` its type is `%s`.' %
                            (str(arg_0), repr(type(arg_0))))

        if type(arg_0) in (list, tuple):
            # If data is a list or tuple we need to remember the data type of the elements
            # in the list or tuple.
            # We do NOT need to remember the elements of `dict` explicitly, though.
            # `dict` is stored
            # as an `ObjectTable` and thus types are already conserved.
            if len(arg_0) > 0:
                arg_3 = type(arg_0[0]).__name__

                if not arg_3 in pypetconstants.PARAMETERTYPEDICT:
                    raise TypeError('I do not know how to handle `%s` its type is '
                                    '`%s`.' % (str(arg_0), arg_3))

                HDF5StorageService._all_set_attr(arg_1, arg_2 +
                                       HDF5StorageService.SCALAR_TYPE, arg_3)
        elif (type(arg_0) in (np.ndarray, np.matrix) and
                  np.issubdtype(arg_0.dtype, str)):
            HDF5StorageService._all_set_attr(arg_1, arg_2 + HDF5StorageService.SCALAR_TYPE,
                                   str.__name__)


def Func(arg_0, arg_1, arg_2, arg_3):
        """Checks if loaded data has the type it was stored in. If not converts it.

        :param data: Data item to be checked and converted
        :param ptitem: HDf5 Node or Leaf from where data was loaded
        :param prefix: Prefix for recalling the data type from the hdf5 node attributes

        :return:

            Tuple, first item is the (converted) `data` item, second boolean whether
            item was converted or not.

        """
        arg_4 = arg_0._all_get_from_attrs(arg_2, arg_3 + HDF5StorageService.SCALAR_TYPE)
        arg_5 = arg_0._all_get_from_attrs(arg_2, arg_3 + HDF5StorageService.COLL_TYPE)
        arg_6 = False

        # Check what the original data type was from the hdf5 node attributes
        if arg_5 == HDF5StorageService.COLL_SCALAR:
            # Here data item was a scalar

            if isinstance(arg_1, np.ndarray):
                # If we recall a numpy scalar, pytables loads a 1d array :-/
                # So we have to change it to a real scalar value
                arg_1 = np.array([arg_1])[0]
                arg_6 = True

            if not arg_4 is None:
                # Check if current type and stored type match
                # if not convert the data
                if arg_4 != type(arg_1).__name__:

                    if arg_4 == str.__name__:
                        arg_1 = arg_1.decode(arg_0._encoding)
                    else:
                        try:
                            arg_1 = pypetconstants.PARAMETERTYPEDICT[arg_4](arg_1)
                        except KeyError:
                            # For compatibility with files from older pypet versions
                            arg_1 = pypetconstants.COMPATPARAMETERTYPEDICT[arg_4](arg_1)

                    arg_6 = True

        elif (arg_5 == HDF5StorageService.COLL_TUPLE or
                        arg_5 == HDF5StorageService.COLL_LIST):
            # Here data item was originally a tuple or a list

            if type(arg_1) is not list and type is not tuple:
                # If the original type cannot be recalled, first convert it to a list
                arg_6 = True
                arg_1 = list(arg_1)

            if len(arg_1) > 0:
                arg_7 = arg_1[0]
                # Check if the type of the first item was conserved
                if not arg_4 == type(arg_7).__name__:

                    if not isinstance(arg_1, list):
                        arg_1 = list(arg_1)

                    # If type was not conserved we need to convert all items
                    # in the list or tuple
                    for arg_8, arg_9 in enumerate(arg_1):
                        if arg_4 == str.__name__:
                            arg_1[arg_8] = arg_1[arg_8].decode(arg_0._encoding)
                        else:
                            try:
                                arg_1[arg_8] = pypetconstants.PARAMETERTYPEDICT[arg_4](arg_9)
                            except KeyError:
                                # For compatibility with files from older pypet versions:
                                arg_1[arg_8] = pypetconstants.COMPATPARAMETERTYPEDICT[arg_4](arg_9)
                        arg_6 = True

            if arg_5 == HDF5StorageService.COLL_TUPLE:
                # If it was originally a tuple we need to convert it back to tuple
                if type(arg_1) is not tuple:
                    arg_1 = tuple(arg_1)
                    arg_6 = True
        elif arg_5 == HDF5StorageService.COLL_EMPTY_DICT:
            arg_1 = {}
            arg_6 = True
        elif isinstance(arg_1, np.ndarray):

            if arg_4 == str.__name__:
                arg_1 = np.core.defchararray.decode(arg_1, arg_0._encoding)
                arg_6 = True

            if arg_5 == HDF5StorageService.COLL_MATRIX:
                # Here data item was originally a matrix
                arg_1 = np.matrix(arg_1)
                arg_6 = True

        return arg_1, arg_6


def Func(arg_0, arg_1, arg_2, arg_3, arg_4=None, arg_5=None,
                               arg_6=None,
                               arg_7=(arg_8, arg_9,)):
        """Adds or changes a row in a pytable.

        :param item_name: Name of item, the row is about, only important for throwing errors.

        :param insert_dict:

            Dictionary of data that is about to be inserted into the pytables row.

        :param table:

            The table to insert or modify a row in

        :param index:

            Index of row to be modified. Instead of an index a search condition can be
            used as well, see below.

        :param condition:

            Condition to search for in the table

        :param condvars:

            Variables for the search condition

        :param flags:

            Flags whether to add, modify, or remove a row in the table

        """
        if len(arg_7) == 0:
            # No flags means no-op
            return

        # You can only specify either an index or a condition not both
        if arg_4 is not None and arg_5 is not None:
            raise ValueError('Please give either a condition or an index or none!')
        elif arg_5 is not None:
            arg_10 = arg_3.where(arg_5, arg_6=arg_6)
        elif arg_4 is not None:
            arg_10 = arg_3.iterrows(arg_4, arg_4 + 1)
        else:
            arg_10 = None

        try:
            arg_11 = next(arg_10)
        except TypeError:
            arg_11 = None
        except StopIteration:
            arg_11 = None

        # multiple_entries = []

        if ((HDF5StorageService.MODIFY_ROW in arg_7 or HDF5StorageService.ADD_ROW in arg_7) and
                    HDF5StorageService.REMOVE_ROW in arg_7):
            # You cannot remove and modify or add at the same time
            raise ValueError('You cannot add or modify and remove a row at the same time.')

        if arg_11 is None and HDF5StorageService.ADD_ROW in arg_7:
            # Here we add a new row

            arg_11 = arg_3.row

            arg_0._all_insert_into_row(arg_11, arg_2)

            arg_11.append()

        elif arg_11 is not None and HDF5StorageService.MODIFY_ROW in arg_7:
            # Here we modify an existing row

            arg_0._all_insert_into_row(arg_11, arg_2)

            arg_11.update()

        elif HDF5StorageService.REMOVE_ROW in arg_7:
            # Here we delete an existing row

            if arg_11 is not None:
                # Only delete if the row does exist otherwise we do not have to do anything
                arg_12 = arg_11.nrow
                try:
                    arg_3.remove_rows(start=arg_12, stop=arg_12+1)
                except NotImplementedError:
                    pass
                    # We get here if we try to remove the last row of a table
                    # there is nothing we can do but keep it :-(
        else:
            raise ValueError('Something is wrong, you might not have found '
                             'a row, or your flags are not set appropriately')

        arg_0._all_kill_iterator(arg_10)
        arg_3.flush()

        if HDF5StorageService.REMOVE_ROW not in arg_7 and arg_11 is None:
            raise RuntimeError('Could not add or modify entries of `%s` in '
                               'table %s' % (arg_1, arg_3._v_name))


def Func(arg_0, arg_1, arg_2=None):
        """Creates or returns a group"""
        if not arg_1 in arg_2:
            arg_3 = arg_0._hdf5file.create_group(where=arg_2,
                                                      arg_1=arg_1,
                                                      title=arg_1,
                                                      filters=arg_0._all_get_filters())
            return arg_3, True
        else:
            arg_3 = arg_2._f_get_child(arg_1)
            return arg_3, False


def Func(arg_0, arg_1, arg_2, arg_3=False):
        """Stores annotations into an hdf5 file."""

        # If we overwrite delete all annotations first
        if arg_3 is True or arg_3 == 'v_annotations':
            arg_4 = arg_0._all_get_from_attrs(arg_2, HDF5StorageService.ANNOTATED)
            if arg_4:
                arg_5 = arg_2._v_attrs
                for arg_6 in arg_5._v_attrnames:
                    if arg_6.startswith(HDF5StorageService.ANNOTATION_PREFIX):
                        delattr(arg_5, arg_6)
                delattr(arg_5, HDF5StorageService.ANNOTATED)
                arg_0._hdf5file.flush()

        # Only store annotations if the item has some
        if not arg_1.v_annotations.f_is_empty():

            arg_7 = arg_1.v_annotations._dict

            arg_5 = arg_2._v_attrs

            arg_8 = False

            for arg_9 in arg_7:
                arg_10 = arg_7[arg_9]

                arg_11 = HDF5StorageService.ANNOTATION_PREFIX + arg_9
                if arg_11 not in arg_5:
                    # Only store *new* annotations, if they already exist on disk, skip storage
                    setattr(arg_5, arg_11, arg_10)
                    arg_8 = True

            if arg_8:
                setattr(arg_5, HDF5StorageService.ANNOTATED, True)
                arg_0._hdf5file.flush()


def Func(arg_0, arg_1, arg_2=arg_3.STORE_DATA,
                         arg_5=True, arg_6=False, arg_7=None,
                         arg_8=None, arg_9=False):
        """Stores a group node.

        For group nodes only annotations and comments need to be stored.

        """
        if arg_2 == arg_3.STORE_NOTHING:
            return
        elif arg_2 == arg_3.STORE_DATA_SKIPPING and arg_1._stored:
            arg_0._logger.debug('Already found `%s` on disk I will not store it!' %
                                   arg_1.v_full_name)
        elif not arg_6:
            if arg_8 is None:
                arg_8, arg_9 = arg_0._all_create_or_get_groups(arg_1.v_full_name)

            arg_10 = arg_2 == arg_3.OVERWRITE_DATA

            if (arg_1.v_comment != '' and
                    (HDF5StorageService.COMMENT not in arg_8._v_attrs or arg_10)):
                setattr(arg_8._v_attrs, HDF5StorageService.COMMENT, arg_1.v_comment)

            if ((arg_9 or arg_10) and
                type(arg_1) not in (nn.NNGroupNode, nn.ConfigGroup, nn.ParameterGroup,
                                             nn.DerivedParameterGroup, nn.ResultGroup)):
                # We only store the name of the class if it is not one of the standard groups,
                # that are always used.
                setattr(arg_8._v_attrs, HDF5StorageService.CLASS_NAME,
                        arg_1.f_get_class_name())

            arg_0._ann_store_annotations(arg_1, arg_8, arg_10=arg_10)
            arg_0._hdf5file.flush()
            arg_1._stored = True

            # Signal completed node loading
            arg_0._node_processing_timer.signal_update()

        if arg_6:
            arg_12 = arg_1.f_get_parent()
            arg_13 = arg_0._all_create_or_get_groups(arg_12.v_full_name)[0]

            arg_0._tree_store_nodes_dfs(arg_12, arg_1.v_name, arg_2=arg_2,
                                       arg_5=arg_5, arg_6=arg_6,
                                       arg_7=arg_7, current_depth=0,
                                       arg_13=arg_13)


def Func(arg_0, arg_1, arg_2=arg_3.LOAD_DATA, arg_5=True,
                        arg_6=False, arg_7=None,
                        arg_8=None, arg_9=False, arg_10=None):
        """Loads a group node and potentially everything recursively below"""
        if arg_10 is None:
            arg_10 = arg_0._all_get_node_by_name(arg_1.v_full_name)
            arg_8 = arg_1.v_root

        if arg_6:
            arg_11 = arg_1.f_get_parent()
            arg_0._tree_load_nodes_dfs(arg_11, arg_2=arg_2, arg_5=arg_5,
                                  arg_6=arg_6, arg_7=arg_7,
                                  current_depth=0,
                                  trajectory=arg_8, as_new=arg_9,
                                  hdf5_group=arg_10)
        else:
            if arg_2 == arg_3.LOAD_NOTHING:
                return

            elif arg_2 == arg_3.OVERWRITE_DATA:
                arg_1.v_annotations.f_empty()
                arg_1.v_comment = ''

            arg_0._all_load_skeleton(arg_1, arg_10)
            arg_1._stored = not arg_9

            # Signal completed node loading
            arg_0._node_processing_timer.signal_update()


def Func(arg_0, arg_1, arg_2):
        """Reloads skeleton data of a tree node"""
        if arg_1.v_annotations.f_is_empty():
            arg_0._ann_load_annotations(arg_1, arg_2)
        if arg_1.v_comment == '':
            arg_3 = arg_0._all_get_from_attrs(arg_2, HDF5StorageService.COMMENT)
            if arg_3 is None:
                arg_3 = ''
            arg_1.v_comment = arg_3


def Func(arg_0, arg_1):
        """Extracts storage flags for data in `data_dict`
        if they were not specified in `flags_dict`.

        See :const:`~pypet.storageservice.HDF5StorageService.TYPE_FLAG_MAPPING`
        for how to store different types of data per default.

        """
        for arg_2, arg_3 in arg_0.items():
            if not arg_2 in arg_1:
                arg_4 = type(arg_3)
                if (arg_4 is np.ndarray or arg_4 is dict) and len(arg_3) == 0:
                        # Empty containers are stored as an Array
                        # No need to ask for tuple or list, because they are always
                        # stored as arrays.
                        arg_1[arg_2] = HDF5StorageService.ARRAY
                        continue
                else:
                    try:
                        arg_1[arg_2] = HDF5StorageService.TYPE_FLAG_MAPPING[arg_4]
                    except KeyError:
                        raise pex.NoSuchServiceError('I cannot store `%s`, I do not understand the'
                                                     'type `%s`.' % (arg_2, str(arg_4)))


def Func(arg_0, arg_1, arg_2, arg_3=False):
        """Adds information to overview tables and meta information to
        the `instance`s hdf5 `group`.

        :param instance: Instance to store meta info about
        :param group: HDF5 group of instance
        :param overwrite: If data should be explicitly overwritten

        """

        if arg_3:
            arg_4 = ()
        else:
            arg_4 = (HDF5StorageService.ADD_ROW,)

        arg_5 = True
        try:
            # Check if we need to store the comment. Maybe update the overview tables
            # accordingly if the current run index is lower than the one in the table.
            arg_5 = arg_0._prm_meta_add_summary(arg_1)

            try:
                # Update the summary overview table
                arg_6 = arg_1.v_branch + '_overview'

                arg_7 = getattr(arg_0._overview_group, arg_6)
                if len(arg_7) < pypetconstants.HDF5_MAX_OVERVIEW_TABLE_LENGTH:

                    arg_0._all_store_param_or_result_table_entry(arg_1, arg_7,
                                                                arg_4=arg_4)
            except pt.NoSuchNodeError:
                pass
        except Exception as exc:
            arg_0._logger.error('Could not store information table due to `%s`.' % repr(exc))

        if ((not arg_0._purge_duplicate_comments or arg_5) and
                    arg_1.v_comment != ''):
            # Only add the comment if necessary
            setattr(arg_2._v_attrs, HDF5StorageService.COMMENT, arg_1.v_comment)

        # Add class name and whether node is a leaf to the HDF5 attributes
        setattr(arg_2._v_attrs, HDF5StorageService.CLASS_NAME, arg_1.f_get_class_name())
        setattr(arg_2._v_attrs, HDF5StorageService.LEAF, True)

        if arg_1.v_is_parameter and arg_1.v_explored:
            # If the stored parameter was an explored one we need to mark this in the
            # explored overview table
            try:
                arg_8 = 'explored_parameters_overview'
                arg_7 = getattr(arg_0._overview_group, arg_8)

                if len(arg_7) < pypetconstants.HDF5_MAX_OVERVIEW_TABLE_LENGTH:
                    arg_0._all_store_param_or_result_table_entry(arg_1, arg_7,
                                                                arg_4=arg_4)
            except pt.NoSuchNodeError:
                pass
            except Exception as exc:
                arg_0._logger.error('Could not store information '
                                   'table due to `%s`.' % repr(exc))


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, arg_5):
        """Stores a `store_dict`"""
        for arg_6, arg_7 in arg_2.items():
            # self._logger.log(1, 'SUB-Storing %s [%s]', key, str(store_dict[key]))
            arg_8 = None

            arg_9 = arg_4[arg_6]

            if '.' in arg_6:
                arg_8 = arg_3
                arg_10 = arg_6.split('.')
                arg_6 = arg_10.pop()
                for arg_11 in arg_10:
                    arg_3, arg_12 =  arg_0._all_create_or_get_group(arg_11,
                                                                                arg_3)
                    if arg_12:
                        setattr(arg_3._v_attrs, HDF5StorageService.STORAGE_TYPE,
                                HDF5StorageService.NESTED_GROUP)
                    else:
                        arg_13 = arg_0._all_get_from_attrs(arg_3, HDF5StorageService.STORAGE_TYPE)
                        if arg_13 != HDF5StorageService.NESTED_GROUP:
                            raise ValueError('You want to nested results but `%s` is already '
                                             'of type `%s`!' % (arg_3._v_name, arg_13))

            # Iterate through the data and store according to the storage flags
            if arg_6 in arg_3:
                # We won't change any data that is found on disk
                arg_0._logger.debug(
                    'Found %s already in hdf5 node of %s, so I will ignore it.' %
                    (arg_6, arg_1))
                continue

            if arg_9 == HDF5StorageService.TABLE:
                # self._logger.log(1, 'SUB-Storing %s TABLE', key)
                arg_0._prm_write_into_pytable(arg_6, arg_7, arg_3, arg_1,
                                             **arg_5)
            elif arg_9 == HDF5StorageService.DICT:
                # self._logger.log(1, 'SUB-Storing %s DICT', key)
                arg_0._prm_write_dict_as_table(arg_6, arg_7, arg_3, arg_1,
                                              **arg_5)
            elif arg_9 == HDF5StorageService.ARRAY:
                # self._logger.log(1, 'SUB-Storing %s ARRAY', key)
                arg_0._prm_write_into_array(arg_6, arg_7, arg_3, arg_1,
                                           **arg_5)
            elif arg_9 in (HDF5StorageService.CARRAY,
                          HDF5StorageService.EARRAY,
                          HDF5StorageService.VLARRAY):
                arg_0._prm_write_into_other_array(arg_6, arg_7,
                                                 arg_3, arg_1,
                                                 arg_9=arg_9, **arg_5)
            elif arg_9 in (HDF5StorageService.SERIES,
                          HDF5StorageService.FRAME,
                          #  HDF5StorageService.PANEL
                          ):
                # self._logger.log(1, 'SUB-Storing %s PANDAS', key)
                arg_0._prm_write_pandas_data(arg_6, arg_7, arg_3, arg_1,
                                            arg_9, **arg_5)
            elif arg_9 == HDF5StorageService.SHARED_DATA:
                pass  # Shared data needs to be explicitly created and is not stored on
                # the fly
            else:
                raise RuntimeError('You shall not pass!')

            if arg_8 is not None:
                arg_3 = arg_8


def Func(arg_0,
                                       arg_1,
                                       arg_2=arg_3.STORE_DATA,
                                       arg_5=None,
                                       arg_6=None,
                                       arg_7=False,
                                       arg_8=False,
                                       arg_9=None,
                                       arg_10=False,
                                       **arg_11):
        """Stores a parameter or result to hdf5.

        :param instance:

            The instance to be stored

        :param store_data:

            How to store data

        :param store_flags:

            Dictionary containing how to store individual data, usually empty.

        :param overwrite:

            Instructions how to overwrite data

        :param with_links:

            Placeholder because leaves have no links

        :param recursive:

            Placeholder, because leaves have no children

        :param _hdf5_group:

            The hdf5 group for storing the parameter or result

        :param _newly_created:

            If should be created in a new form

        """
        if arg_2 == arg_3.STORE_NOTHING:
            return
        elif arg_2 == arg_3.STORE_DATA_SKIPPING and arg_1._stored:
            arg_0._logger.debug('Already found `%s` on disk I will not store it!' %
                                   arg_1.v_full_name)
            return
        elif arg_2 == arg_3.OVERWRITE_DATA:
            if not arg_6:
                arg_6 = True

        arg_12 = arg_1.v_full_name
        arg_0._logger.debug('Storing `%s`.' % arg_12)

        if arg_9 is None:
            # If no group is provided we might need to create one
            arg_9, arg_10 = arg_0._all_create_or_get_groups(arg_12)

        # kwargs_flags = {} # Dictionary to change settings
        # old_kwargs = {}
        arg_13 = {}
        # If the user did not supply storage flags, we need to set it to the empty dictionary
        if arg_5 is None:
            arg_5 = {}

        try:
            # Get the data to store from the instance
            if not arg_1.f_is_empty():
                arg_13 = arg_1._store()
            try:
                # Ask the instance for storage flags
                arg_14 = arg_1._store_flags().copy() # copy to avoid modifying the
                # original data
            except AttributeError:
                # If it does not provide any, set it to the empty dictionary
                arg_14 = {}

            # User specified flags have priority over the flags from the instance
            arg_14.update(arg_5)
            arg_5 = arg_14

            # If we still have data in `store_dict` about which we do not know how to store
            # it, pick default storage flags
            arg_0._prm_extract_missing_flags(arg_13, arg_5)

            if arg_6:
                if isinstance(arg_6, str):
                    arg_6 = [arg_6]

                if arg_6 is True:
                    arg_15 = [arg_21 for arg_21 in arg_13.keys() if arg_21 in arg_9]
                    arg_0._all_delete_parameter_or_result_or_group(arg_1,
                                                                  delete_only=arg_15,
                                                                  arg_9=arg_9)
                elif isinstance(arg_6, (list, tuple)):
                    arg_16 = set(arg_6)
                    arg_17 = set(arg_13.keys())

                    arg_18 = arg_16 - arg_17

                    if arg_6!='v_annotations' and len(arg_18) > 0:
                        arg_0._logger.warning('Cannot overwrite `%s`, these items are not supposed to '
                                             'be stored by the leaf node.' %
                                             str(arg_18))

                    arg_19 = arg_16 & arg_17
                    if len(arg_19) > 0:
                        arg_0._all_delete_parameter_or_result_or_group(arg_1,
                                                                      delete_only=list(
                                                                          arg_19))
                else:
                    raise ValueError('Your value of overwrite `%s` is not understood. '
                                     'Please pass `True` of a list of strings to fine grain '
                                     'overwriting.' % str(arg_6))

            arg_0._prm_store_from_dict(arg_12, arg_13, arg_9, arg_5, arg_11)

            # Store annotations
            arg_0._ann_store_annotations(arg_1, arg_9, arg_6=arg_6)

            if arg_10 or arg_6 is True:
                # If we created a new group or the parameter was extended we need to
                # update the meta information and summary tables
                arg_0._prm_add_meta_info(arg_1, arg_9,
                                        arg_6=not arg_10)

            arg_1._stored = True

            #self._logger.debug('Finished Storing `%s`.' % fullname)
            # Signal completed node loading
            arg_0._node_processing_timer.signal_update()

        except:
            # I anything fails, we want to remove the data of the parameter again
            arg_0._logger.error(
                'Failed storing leaf `%s`. I will remove the hdf5 data I added  again.' % arg_12)
            # Delete data
            for arg_21 in arg_13.keys():
                if arg_21 in  arg_9:
                    arg_22 = arg_9._f_get_child(arg_21)
                    arg_22._f_remove(arg_8=True)
            # If no data left delete the whole parameter
            if arg_9._v_nchildren == 0:
                arg_9._f_remove(arg_8=True)
            raise


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, **arg_6):
        """Creates and array that can be used with an HDF5 array object"""

        if arg_5 == HDF5StorageService.ARRAY:
            arg_0._prm_write_into_array(arg_1, arg_2, arg_3, arg_4, **arg_6)
        elif arg_5 in (HDF5StorageService.CARRAY,
                    HDF5StorageService.EARRAY,
                    HDF5StorageService.VLARRAY):
            arg_0._prm_write_into_other_array(arg_1, arg_2, arg_3, arg_4,
                                             arg_5=arg_5, **arg_6)
        else:
            raise RuntimeError('Flag `%s` of hdf5 data `%s` of `%s` not understood' %
                               (arg_5, arg_1, arg_4))

        arg_0._hdf5file.flush()


def Func(arg_0, arg_1, arg_2, arg_3, **arg_4):
        """Creates a new empty table"""
        arg_5 = None
        arg_6 = None
        if 'first_row' in arg_4:
            arg_5 = arg_4.pop('first_row')
            if not 'description' in arg_4:
                arg_6 = {}
                for arg_7 in arg_5:
                    arg_8 = arg_5[arg_7]
                    arg_9 = arg_0._all_get_table_col(arg_1, [arg_8], arg_3)
                    arg_6[arg_7] = arg_9

        if 'description' in arg_4:
            arg_6 = arg_4.pop('description')

        if 'filters' in arg_4:
            arg_10 = arg_4.pop('filters')
        else:
            arg_10 = arg_0._all_get_filters(arg_4)

        arg_11 = arg_0._hdf5file.create_table(where=arg_2, name=arg_1,
                                          arg_6=arg_6,
                                          arg_10=arg_10,
                                          **arg_4)
        arg_11.flush()

        if arg_5 is not None:
            arg_12 = arg_11.row
            for arg_1 in arg_6:
                arg_12[arg_1] = arg_5[arg_1]

            arg_12.append()
            arg_11.flush()


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, **arg_6):
        """Stores a pandas DataFrame into hdf5.

        :param key:

            Name of data item to store

        :param data:

            Pandas Data to Store

        :param group:

            Group node where to store data in hdf5 file

        :param fullname:

            Full name of the `data_to_store`s original container, only needed for throwing errors.

        :param flag:

            If it is a series, frame or panel

        """
        try:
            if 'filters' not in arg_6:
                arg_7 = arg_0._all_get_filters(arg_6)
                arg_6['filters'] = arg_7
            if 'format' not in arg_6:
                arg_6['format'] = arg_0.pandas_format
            if 'encoding' not in arg_6:
                arg_6['encoding'] = arg_0.encoding

            arg_8 = arg_6.pop('overwrite', False)

            if arg_1 in arg_3 and not (arg_8 or arg_6.get('append', False)):
                raise ValueError(
                    'DataFrame `%s` already exists in `%s`. '
                    'To append pass ``append=`True```.' % (arg_1, arg_4))
            else:
                arg_0._logger.debug('Appending to pandas data `%s` in `%s`' % (arg_1, arg_4))

            if arg_2 is not None and (arg_6['format'] == 'f' or arg_6['format'] == 'fixed'):
                arg_6['expectedrows'] = arg_2.shape[0]

            arg_9 = arg_3._v_pathname + '/' + arg_1
            arg_0._hdf5store.put(arg_9, arg_2, **arg_6)
            arg_0._hdf5store.flush()
            arg_0._hdf5file.flush()

            arg_10 = arg_3._f_get_child(arg_1)
            setattr(arg_10._v_attrs, HDF5StorageService.STORAGE_TYPE, arg_5)
            arg_0._hdf5file.flush()

        except:
            arg_0._logger.error('Failed storing pandas data `%s` of `%s`.' % (arg_1, arg_4))
            raise


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, **arg_5):
        """Stores data as array.

        :param key:

            Name of data item to store

        :param data:

            Data to store

        :param group:

            Group node where to store data in hdf5 file

        :param fullname:

            Full name of the `data_to_store`s original container, only needed for throwing errors.

        :param recall:

            If container type and data type for perfect recall should be stored

        """

        try:
            if arg_1 in arg_3:
                raise ValueError(
                    'Array `%s` already exists in `%s`. Appending is not supported (yet).')

            try:

                arg_6 = arg_0._hdf5file.create_array(where=arg_3,
                                              name=arg_1, obj=arg_2, **arg_5)
            except (TypeError, ValueError) as exc:
                try:
                    if type(arg_2) is dict and len(arg_2) == 0:
                        # We cannot store an empty dictionary,
                        # but we can use an empty tuple as a dummy.
                        arg_7 = ()
                    elif isinstance(arg_2, str):
                        arg_7 = arg_2.encode(arg_0._encoding)
                    elif isinstance(arg_2, int):
                        arg_7 = np.int64(arg_2)
                    else:
                        arg_7 = []
                        for arg_8 in arg_2:
                            arg_7.append(arg_8.encode(arg_0._encoding))
                    arg_6 = arg_0._hdf5file.create_array(where=arg_3,
                                                  name=arg_1, obj=arg_7, **arg_5)
                except Exception:
                    # Re-raise original error
                    raise exc

            if arg_2 is not None:
                # Remember the types of the original data to recall them on loading
                arg_0._all_set_attributes_to_recall_natives(arg_2, arg_6,
                                                           HDF5StorageService.DATA_PREFIX)
            setattr(arg_6._v_attrs, HDF5StorageService.STORAGE_TYPE,
                    HDF5StorageService.ARRAY)
            arg_0._hdf5file.flush()
        except:
            arg_0._logger.error('Failed storing array `%s` of `%s`.' % (arg_1, arg_4))
            raise


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, **arg_5):
        """Stores data as pytable.

        :param tablename:

            Name of the data table

        :param data:

            Data to store

        :param hdf5_group:

            Group node where to store data in hdf5 file

        :param fullname:

            Full name of the `data_to_store`s original container, only needed for throwing errors.

        """

        arg_6 = arg_2.shape[0]

        try:

            # Get a new pytables description from the data and create a new table
            arg_7, arg_8 = arg_0._prm_make_description(arg_2, arg_4)
            arg_9 = [{}]

            if len(arg_7) > ptpa.MAX_COLUMNS:
                # For optimization we want to store the original data types into another table
                # and split the tables into several ones
                arg_10 = arg_0._hdf5file.create_group(where=arg_3,
                                                    name=arg_1,
                                                    filters=arg_0._all_get_filters(arg_5.copy()))

                arg_11 = 0
                for arg_12 in arg_7:
                    arg_13 = arg_7[arg_12]
                    if arg_11 == ptpa.MAX_COLUMNS:
                        arg_9.append({})
                        arg_11 = 0
                    arg_9[-1][arg_12] = arg_13
                    arg_11 += 1

                setattr(arg_10._v_attrs, HDF5StorageService.STORAGE_TYPE,
                        HDF5StorageService.TABLE)
                setattr(arg_10._v_attrs, HDF5StorageService.SPLIT_TABLE, 1)

                arg_3 = arg_10
            else:
                arg_9 = [arg_7]

            for arg_14, arg_15 in enumerate(arg_9):

                if arg_14 == 0:
                    arg_16 = arg_1
                else:
                    arg_16 = arg_1 + '_%d' % arg_14

                arg_17 = arg_0._hdf5file.create_table(where=arg_3, name=arg_16,
                                              description=arg_15,
                                              title=arg_16,
                                              expectedrows=arg_6,
                                              filters=arg_0._all_get_filters(arg_5.copy()))

                arg_18 = arg_17.row
                for arg_19 in range(arg_6):
                    # Fill the columns with data, note if the parameter was extended nstart!=0

                    for arg_20 in arg_15:
                        arg_18[arg_20] = arg_2[arg_20][arg_19]

                    arg_18.append()

                # Remember the original types of the data for perfect recall
                if arg_14 == 0 and len(arg_7) <= ptpa.MAX_COLUMNS:
                    # We only have a single table and
                    # we can store the original data types as attributes
                    for arg_21 in arg_8:
                        arg_22 = arg_8[arg_21]
                        arg_0._all_set_attr(arg_17, arg_21, arg_22)

                    setattr(arg_17._v_attrs, HDF5StorageService.STORAGE_TYPE,
                            HDF5StorageService.TABLE)

                arg_17.flush()
                arg_0._hdf5file.flush()

            if len(arg_7) > ptpa.MAX_COLUMNS:
                # We have potentially many split tables and the data types are
                # stored into an additional table for performance reasons
                arg_16 = arg_1 + '__' + HDF5StorageService.STORAGE_TYPE
                arg_23, arg_24 = list(zip(*arg_8.items()))
                arg_25 = {'field_name': arg_23, 'data_type': arg_24}
                arg_15, arg_26 = arg_0._prm_make_description(arg_25, arg_4)

                arg_17 = arg_0._hdf5file.create_table(where=arg_3, name=arg_16,
                                              description=arg_15,
                                              title=arg_16,
                                              expectedrows=len(arg_23),
                                              filters=arg_0._all_get_filters(arg_5))

                arg_18 = arg_17.row

                for arg_19 in range(len(arg_23)):
                    # Fill the columns with data

                    for arg_20 in arg_25:
                        arg_18[arg_20] = arg_25[arg_20][arg_19]

                    arg_18.append()

                setattr(arg_17._v_attrs, HDF5StorageService.DATATYPE_TABLE, 1)

                arg_17.flush()
                arg_0._hdf5file.flush()

        except:
            arg_0._logger.error('Failed storing table `%s` of `%s`.' % (arg_1, arg_4))
            raise


def Func(arg_0, arg_1, arg_2):
        """ Returns a description dictionary for pytables table creation"""

        def _convert_lists_and_tuples(arg_3):
            """Converts lists and tuples to numpy arrays"""
            if isinstance(arg_3[0],
                          (list, tuple)):  # and not isinstance(series_of_data[0], np.ndarray):
                # If the first data item is a list, the rest must be as well, since
                # data has to be homogeneous
                for arg_4, arg_5 in enumerate(arg_3):
                    arg_3[arg_4] = np.array(arg_5)

        arg_6 = {}  # dictionary containing the description to build a pytables table
        arg_7 = {}  # dictionary containing the original data types

        for arg_8 in arg_1:
            arg_9 = arg_1[arg_8]

            # remember the original data types
            arg_0._all_set_attributes_to_recall_natives(arg_9[0], PTItemMock(arg_7),
                                                       HDF5StorageService.FORMATTED_COLUMN_PREFIX %
                                                       arg_8)

            _convert_lists_and_tuples(arg_9)

            # get a pytables column from the data
            arg_10 = arg_0._all_get_table_col(arg_8, arg_9, arg_2)

            arg_6[arg_8] = arg_10

        return arg_6, arg_7


def Func(arg_0, arg_1, arg_2, arg_3):
        """ Creates a pytables column instance.

        The type of column depends on the type of `column[0]`.
        Note that data in `column` must be homogeneous!

        """
        arg_4 = arg_2[0]

        try:

            # # We do not want to loose int_
            if type(arg_4) is int:
                return pt.IntCol()

            if isinstance(arg_4, (str, bytes)):
                arg_5 = int(arg_0._prm_get_longest_stringsize(arg_2))
                return pt.StringCol(arg_5)

            if isinstance(arg_4, np.ndarray):
                if (np.issubdtype(arg_4.dtype, str) or
                        np.issubdtype(arg_4.dtype, bytes)):
                    arg_5 = int(arg_0._prm_get_longest_stringsize(arg_2))
                    return pt.StringCol(arg_5, shape=arg_4.shape)
                else:
                    return pt.Col.from_dtype(np.dtype((arg_4.dtype, arg_4.shape)))
            else:
                return pt.Col.from_dtype(np.dtype(type(arg_4)))
        except Exception:
            arg_0._logger.error('Failure in storing `%s` of Parameter/Result `%s`.'
                               ' Its type was `%s`.' % (arg_1, arg_3, repr(type(arg_4))))
            raise


def Func(arg_0):
        """ Returns the longest string size for a string entry across data."""
        arg_1 = 1

        for arg_2 in arg_0:
            if isinstance(arg_2, np.ndarray):
                if arg_2.ndim > 0:
                    for arg_3 in arg_2.ravel():
                        arg_1 = max(len(arg_3), arg_1)
                else:
                    arg_1 = max(len(arg_2.tolist()), arg_1)
            else:
                arg_1 = max(len(arg_2), arg_1)

        # Make the string Col longer than needed in order to allow later on slightly larger strings
        return int(arg_1 * 1.5)


def Func(arg_0, arg_1, arg_2, arg_3, arg_4,
                            arg_5, arg_6, arg_7, arg_8 = ''):
        """Loads into dictionary"""
        for arg_9 in arg_3:

            arg_10 = arg_0._all_get_from_attrs(arg_9, HDF5StorageService.STORAGE_TYPE)

            if arg_8:
                arg_11 = '%s.%s' % (arg_8, arg_9._v_name)
            else:
                arg_11 = arg_9._v_name

            if arg_10 == HDF5StorageService.NESTED_GROUP:
                arg_0.Func(arg_1=arg_1,
                                         arg_2=arg_2,
                                         arg_3=arg_9,
                                         arg_4=arg_4,
                                         arg_5=arg_5,
                                         arg_6=arg_6,
                                         arg_7=arg_7,
                                         arg_8=arg_11)
                continue

            if arg_5 is not None:

                if arg_11 not in arg_5:
                    continue
                else:
                    arg_5.remove(arg_11)

            elif arg_6 is not None:
                if arg_11 in arg_6:
                    arg_6.remove(arg_11)
                    continue

            # Recall from the hdf5 node attributes how the data was stored and reload accordingly
            if arg_11 in arg_7:
                arg_10 = arg_7[arg_11]

            if arg_10 == HDF5StorageService.DICT:
                arg_12 = arg_0._prm_read_dictionary(arg_9, arg_1)
            elif arg_10 == HDF5StorageService.TABLE:
                arg_12 = arg_0._prm_read_table(arg_9, arg_1)
            elif arg_10 in (HDF5StorageService.ARRAY, HDF5StorageService.CARRAY,
                                HDF5StorageService.EARRAY, HDF5StorageService.VLARRAY):
                arg_12 = arg_0._prm_read_array(arg_9, arg_1)
            elif arg_10 in (HDF5StorageService.FRAME,
                               HDF5StorageService.SERIES,
                               #  HDF5StorageService.PANEL
                               ):
                arg_12 = arg_0._prm_read_pandas(arg_9, arg_1)
            elif arg_10.startswith(HDF5StorageService.SHARED_DATA):
                arg_12 = arg_0._prm_read_shared_data(arg_9, arg_4)
            else:
                raise pex.NoSuchServiceError('Cannot load %s, do not understand the hdf5 file '
                                             'structure of %s [%s].' %
                                             (arg_1, str(arg_9), str(arg_10)))

            if arg_12 is None:
                raise RuntimeError('You shall not pass!')

            arg_2[arg_11] = arg_12


def Func(arg_0, arg_1, arg_2):
        """Loads data that was originally a dictionary when stored

        :param leaf:

            PyTables table containing the dictionary data

        :param full_name:

            Full name of the parameter or result whose data is to be loaded

        :return:

            Data to be loaded

        """
        try:
            # Load as Pbject Table
            arg_3 = arg_0._prm_read_table(arg_1, arg_2)
            # Turn the ObjectTable into a dictionary of lists (with length 1).
            arg_4 = arg_3.to_dict('list')

            arg_5 = {}

            # Turn the dictionary of lists into a normal dictionary
            for arg_6, arg_7 in arg_4.items():
                arg_5[arg_6] = arg_7[0]

            return arg_5
        except:
            arg_0._logger.error('Failed loading `%s` of `%s`.' % (arg_1._v_name, arg_2))
            raise


def Func(arg_0, arg_1, arg_2):
        """Reads shared data and constructs the appropraite class.

        :param shared_node:

            hdf5 node storing the pandas DataFrame

        :param full_name:

            Full name of the parameter or result whose data is to be loaded

        :return:

            Data to load

        """
        try:
            arg_3 = arg_0._all_get_from_attrs(arg_1,
                                                 HDF5StorageService.SHARED_DATA_TYPE)
            arg_4 = shared.FLAG_CLASS_MAPPING[arg_3]
            arg_5 = arg_1._v_name
            arg_6 = arg_4(arg_5=arg_5, parent=arg_2)
            return arg_6
        except:
            arg_0._logger.error('Failed loading `%s` of `%s`.' % (arg_1._v_name,
                                                                 arg_2.v_full_name))
            raise


def Func(arg_0, arg_1, arg_2):
        """Reads a non-nested PyTables table column by column and created a new ObjectTable for
        the loaded data.

        :param table_or_group:

            PyTables table to read from or a group containing subtables.

        :param full_name:

            Full name of the parameter or result whose data is to be loaded

        :return:

            Data to be loaded

        """
        try:
            arg_3 = None

            if arg_0._all_get_from_attrs(arg_1, HDF5StorageService.SPLIT_TABLE):
                arg_4 = arg_1._v_name

                arg_5 = arg_4 + '__' + HDF5StorageService.STORAGE_TYPE

                arg_6 = arg_1._v_children[arg_5]
                arg_7 = {}

                for arg_8 in arg_6:
                    arg_9 = arg_8['field_name'].decode('utf-8')
                    arg_7[arg_9] = arg_8['data_type'].decode('utf-8')

                for arg_10 in arg_1:
                    arg_11 = arg_10._v_name

                    if arg_11 == arg_5:
                        continue

                    for arg_12 in arg_10.colnames:
                        # Read Data column by column
                        arg_13 = arg_10.col(arg_12)
                        arg_14 = list(arg_13)

                        arg_15 = HDF5StorageService.FORMATTED_COLUMN_PREFIX % arg_12
                        for arg_16, arg_17 in enumerate(arg_14):
                            # Recall original type of data
                            arg_17, arg_18 = arg_0._all_recall_native_type(arg_17,
                                                                              PTItemMock(
                                                                                arg_7),
                                                                              arg_15)
                            if arg_18:
                                arg_14[arg_16] = arg_17
                            else:
                                break

                        # Construct or insert into an ObjectTable
                        if arg_3 is None:
                            arg_3 = ObjectTable(arg_17={arg_12: arg_14})
                        else:
                            arg_3[arg_12] = arg_14

            else:
                for arg_12 in arg_1.colnames:
                    # Read Data column by column
                    arg_13 = arg_1.col(arg_12)
                    arg_14 = list(arg_13)

                    arg_15 = HDF5StorageService.FORMATTED_COLUMN_PREFIX % arg_12
                    for arg_16, arg_17 in enumerate(arg_14):
                        # Recall original type of data
                        arg_17, arg_18 = arg_0._all_recall_native_type(arg_17, arg_1,
                                                                          arg_15)
                        if arg_18:
                            arg_14[arg_16] = arg_17
                        else:
                            break

                    # Construct or insert into an ObjectTable
                    if arg_3 is None:
                        arg_3 = ObjectTable(arg_17={arg_12: arg_14})
                    else:
                        arg_3[arg_12] = arg_14

            return arg_3
        except:
            arg_0._logger.error(
                'Failed loading `%s` of `%s`.' % (arg_1._v_name, arg_2))
            raise


def Func(arg_0, arg_1, arg_2):
        """Reads data from an array or carray

        :param array:

            PyTables array or carray to read from

        :param full_name:

            Full name of the parameter or result whose data is to be loaded

        :return:

            Data to load

        """
        try:
            arg_3 = arg_0._svrc_read_array(arg_1)
            # Recall original data types
            arg_3, arg_4 = arg_0._all_recall_native_type(arg_3, arg_1,
                                                         HDF5StorageService.DATA_PREFIX)

            return arg_3
        except:
            arg_0._logger.error('Failed loading `%s` of `%s`.' % (arg_1._v_name, arg_2))
            raise


def Func(arg_0=None,
                    arg_1=None,
                    arg_2=False,
                    arg_3=arg_4.LOAD_DATA,
                    arg_6=arg_4.LOAD_SKELETON,
                    arg_8=arg_4.LOAD_SKELETON,
                    arg_9=arg_4.LOAD_SKELETON,
                    arg_10=True,
                    arg_11=None,
                    arg_12=None,
                    arg_13=False,
                    arg_14=None,
                    arg_15='my_trajectory',
                    arg_16=True,
                    arg_17=None,
                    arg_18=True,
                    arg_19=arg_20.HDF5StorageService,
                    **arg_22):
    """Helper function that creates a novel trajectory and loads it from disk.

    For the parameters see :func:`~pypet.trajectory.Trajectory.f_load`.

    ``new_name`` and ``add_time`` are only used in case ``as_new`` is ``True``.
    Accordingly, they determine the new name of trajectory.

    """
    if arg_0 is None and arg_1 is None:
        raise ValueError('Please specify either a name or an index')
    elif arg_0 is not None and arg_1 is not None:
        raise ValueError('Please specify either a name or an index')

    arg_23 = Trajectory(arg_0=arg_15, arg_16=arg_16, arg_14=arg_14,
                      arg_17=arg_17)
    arg_23.f_load(arg_0=arg_0, arg_1=arg_1, arg_2=arg_2, arg_3=arg_3,
                arg_6=arg_6, arg_8=arg_8,
                arg_9=arg_9, arg_10=arg_10, arg_11=arg_11,
                arg_12=arg_12, arg_13=arg_13, arg_18=arg_18,
                arg_19=arg_19, **arg_22)
    return arg_23


def Func(arg_0):
    """Creates a run set name based on ``idx``"""
    arg_1 = 1000
    arg_2 = arg_0 // arg_1
    if arg_2 >= 0:
        return pypetconstants.FORMATTED_SET_NAME % arg_2
    else:
        return pypetconstants.SET_NAME_DUMMY


def Func(arg_0, **arg_1):
        """Sets properties like ``v_fast_access``.

        For example: ``traj.Func(v_fast_access=True, v_auto_load=False)``

        """
        for arg_2 in arg_1:
            arg_3 = arg_1[arg_2]
            if not arg_2.startswith('v_'):
                arg_2 = 'v_' + arg_2
            if not arg_2 in arg_0._nn_interface._not_admissible_names:
                raise AttributeError('Cannot set property `%s` does not exist.' % arg_2)
            else:
                setattr(arg_0, arg_2, arg_3)


def Func(arg_0, arg_1):
        """Adds classes or paths to classes to the trajectory to create custom parameters.

        :param dynamic_imports:

            If you've written custom parameter that needs to be loaded dynamically during runtime,
            this needs to be specified here as a list of classes or strings naming classes
            and there module paths. For example:
            `dynamic_imports = ['pypet.parameter.PickleParameter',MyCustomParameter]`

            If you only have a single class to import, you do not need the list brackets:
            `dynamic_imports = 'pypet.parameter.PickleParameter'`

        """

        if not isinstance(arg_1, (list, tuple)):
            arg_1 = [arg_1]

        for arg_2 in arg_1:
            if not (isinstance(arg_2, str) or inspect.isclass(arg_2)):
                raise TypeError('Your dynamic import `%s` is neither a class nor a string.' %
                                str(arg_2))

        arg_0._dynamic_imports.extend(arg_1)


def Func(arg_0, arg_1=0, arg_2=None, arg_3=1, arg_4='name'):
        """Makes the trajectory iterate over all runs.

        :param start: Start index of run

        :param stop: Stop index, leave ``None`` for length of trajectory

        :param step: Stepsize

        :param yields:

            What should be yielded: ``'name'`` of run, ``idx`` of run
            or ``'self'`` to simply return the trajectory container.

            You can also pick ``'copy'`` to get **shallow** copies (ie the tree is copied but
            no leave nodes except explored ones.) of your trajectory,
            might lead to some of overhead.

        Note that after a full iteration, the trajectory is set back to normal.

        Thus, the following code snippet

        ::

            for run_name in traj.Func():

                 # Do some stuff here...

        is equivalent to

        ::

            for run_name in traj.f_get_run_names(sort=True):
                traj.f_set_crun(run_name)

                # Do some stuff here...

            traj.f_set_crun(None)

        :return:

            Iterator over runs. The iterator itself will return the run names but modify
            the trajectory in each iteration and set it back do normal in the end.

        """
        if arg_2 is None:
            arg_2 =len(arg_0)
        elif arg_2 > len(arg_0):
            raise ValueError('Stop cannot be larger than the trajectory lenght.')
        arg_4 = arg_4.lower()
        if arg_4 == 'name':
            arg_5 = lambda x: arg_0.f_idx_to_run(x)
        elif arg_4 == 'idx':
            arg_5 = lambda x: x
        elif arg_4 == 'self':
            arg_5 = lambda x: arg_0
        elif arg_4 == 'copy':
            arg_5 = lambda x: arg_0.__copy__()
        else:
            raise ValueError('Please choose yields among: `name`, `idx`, or `self`.')
        for arg_6 in range(arg_1, arg_2, arg_3):
            arg_0.f_set_crun(arg_6)
            yield arg_5(arg_6)

        arg_0.f_set_crun(None)


def Func(arg_0, arg_1, arg_2=True, arg_3=False,
                        arg_4=False, arg_5 = True,
                        arg_6=True, arg_7=None, arg_8=False):
        """Searches for all occurrences of `name` in each run.

        Generates an ordered dictionary with the run names or indices as keys and
        found items as values.

        Example:

        >>> traj.Func(self, 'deep.universal_answer', use_indices=True, fast_access=True)
        OrderedDict([(0, 42), (1, 42), (2, 'fortytwo), (3, 43)])

        :param name:

            String description of the item(s) to find.
            Cannot be full names but the part of the names that are below
            a `run_XXXXXXXXX` group.

        :param include_default_run:

            If results found under ``run_ALL`` should be accounted for every run or simply be
            ignored.

        :param use_indices:

            If `True` the keys of the resulting dictionary are the run indices
            (e.g. 0,1,2,3), otherwise the keys are run names (e.g. `run_00000000`,
            `run_000000001`)

        :param fast_access:

            Whether to return parameter or result instances or the values handled by these.

        :param with_links:

            If links should be considered

        :param shortcuts:

            If shortcuts are allowed and the trajectory can *hop* over nodes in the
            path.

        :param max_depth:

            Maximum depth (relative to start node) how search should progress in tree.
            `None` means no depth limit.  Only relevant if `shortcuts` are allowed.

        :param auto_load:

            If data should be loaded from the storage service if it cannot be found in the
            current trajectory tree. Auto-loading will load group and leaf nodes currently
            not in memory and it will load data into empty leaves. Be aware that auto-loading
            does not work with shortcuts.

        :return:

            Ordered dictionary with run names or indices as keys and found items as values.
            Will only include runs where an item was actually found.

        """
        arg_9 = OrderedDict()
        arg_10 = arg_0.v_crun

        try:

            if len(arg_0._run_parent_groups) > 0:
                for arg_11 in arg_0.f_iter_runs():
                    # Iterate over all runs
                    arg_12 = None
                    arg_13 = False
                    for arg_14 in arg_0._run_parent_groups.values():
                        if arg_11 not in arg_14._children:
                            continue

                        try:
                            arg_12 = arg_14.f_get(arg_11 + '.' + arg_1,
                                                           arg_4=False,
                                                           arg_5=arg_5,
                                                           arg_6=arg_6,
                                                           arg_7=arg_7,
                                                           arg_8=arg_8)
                            if arg_13:
                                raise pex.NotUniqueNodeError('`%s` has been found several times '
                                                             'in one run.' % arg_1)
                            else:
                                arg_13 = True

                        except (AttributeError, pex.DataNotInStorageError):
                            pass

                    if arg_12 is None and arg_2:
                        for arg_14 in arg_0._run_parent_groups.values():
                            try:
                                arg_12 = arg_14.f_get(arg_0.f_wildcard('$', -1) +
                                                               '.' + arg_1,
                                                               arg_4=False,
                                                               arg_5=arg_5,
                                                               arg_6=arg_6,
                                                               arg_7=arg_7,
                                                               arg_8=arg_8)
                                if arg_13:
                                    raise pex.NotUniqueNodeError('`%s` has been found several '
                                                                 'times in one run.' % arg_1)
                                else:
                                    arg_13 = True
                            except (AttributeError, pex.DataNotInStorageError):
                                pass

                    if arg_12 is not None:

                        if arg_12.v_is_leaf:
                            arg_12 = arg_0._nn_interface._apply_fast_access(arg_12, arg_4)

                        if arg_3:
                            arg_15 = arg_0.f_idx_to_run(arg_11)
                        else:
                            arg_15 = arg_11

                        arg_9[arg_15] = arg_12

            return arg_9
        finally:
            arg_0.v_crun = arg_10


def Func(arg_0, arg_1=None):
        """Private function such that it can still be called by the environment during
        a single run"""

        if arg_1 is None:
            return all(
                (arg_2['completed'] for arg_2 in arg_0._run_information.values()))
        else:
            return arg_0.f_get_run_information(arg_1, copy=False)['completed']


def Func(arg_0):
        """ Called if trajectory is expanded, deletes all explored parameters from disk """
        for arg_1 in arg_0._explored_parameters.values():
            if arg_1._stored:
                try:
                    arg_0.f_delete_item(arg_1)
                except Exception:
                    arg_0._logger.exception('Could not delete expanded parameter `%s` '
                                           'from disk.' % arg_1.v_full_name)


def Func(arg_0, arg_1,
                          arg_2=True,
                          arg_3=False,
                          arg_4=True):
        """Pass a ``node`` to insert the full tree to the trajectory.

        Considers all links in the given node!
        Ignored nodes already found in the current trajectory.

        :param node: The node to insert

        :param copy_leaves:

            If leaves should be **shallow** copied or simply referred to by both trees.
            **Shallow** copying is established using the copy module.

            Accepts the setting ``'explored'`` to only copy explored parameters.
            Note that ``v_full_copy`` determines how these will be copied.

        :param overwrite:

            If existing elemenst should be overwritten. Requries ``__getstate__`` and
            ``__setstate__`` being implemented in the leaves.

        :param with_links: If links should be ignored or followed and copied as well

        :return: The corresponding (new) node in the tree.

        """

        def _copy_skeleton(arg_5, arg_6):
            """Copies the skeleton of from `node_out` to `node_in`"""
            arg_7 = arg_6.v_annotations
            arg_5._annotations = arg_7
            arg_5.v_comment = arg_6.v_comment

        def _add_leaf(arg_10):
            """Adds a leaf to the trajectory"""
            arg_11 = arg_10.v_full_name
            try:
                arg_12 = arg_0.f_get(arg_11,
                                        arg_4=False,
                                        shortcuts=False,
                                        auto_load=False)
                if arg_3:
                    arg_12.__setstate__(arg_10.__getstate__())
                return arg_12
            except AttributeError:
                pass
            if arg_2 is True or (arg_2 == 'explored' and
                                           arg_10.v_is_parameter and arg_10.v_explored):
                arg_13 = arg_0.f_add_leaf(cp.copy(arg_10))
            else:
                arg_13 = arg_0.f_add_leaf(arg_10)
            if arg_13.v_is_parameter and arg_13.v_explored:
                arg_0._explored_parameters[arg_13.v_full_name] = arg_13
            return arg_13

        def _add_group(arg_16):
            """Adds a new group to the trajectory"""
            arg_17 = arg_16.v_full_name
            try:
                arg_18 = arg_0.f_get(arg_17,
                                             arg_4=False,
                                             shortcuts=False,
                                             auto_load=False)
                if arg_3:
                    _copy_skeleton(arg_18, arg_16)
                return arg_18
            except AttributeError:
                pass
            arg_19 = arg_0.f_add_group(arg_17)
            _copy_skeleton(arg_19, arg_16)
            return arg_19

        arg_20 = arg_0._is_run
        arg_0._is_run = False  # So that we can copy Config Groups and Config Data
        try:
            if arg_1.v_is_leaf:
                return _add_leaf(arg_1)
            elif arg_1.v_is_group:
                arg_22 = arg_1.v_root
                if arg_22 is arg_0:
                    raise RuntimeError('You cannot copy a given tree to itself!')
                arg_23 = _add_group(arg_1)
                arg_24 = arg_1.f_iter_nodes(recursive=True, arg_4=arg_4)
                arg_25 = []
                if arg_1._links:
                    arg_25.append(arg_1)
                for arg_26 in arg_24:
                    if arg_26.v_is_leaf:
                        _add_leaf(arg_26)
                    else:
                        _add_group(arg_26)
                        if arg_26._links:
                            arg_25.append(arg_26)

                if arg_4:
                    for arg_27 in arg_25:
                        arg_28 = arg_0.f_get(arg_27.v_full_name, arg_4=False,
                                          shortcuts=False, auto_load=False)
                        arg_29 = set(arg_28._links.keys())
                        arg_30 = set(arg_27._links.keys())
                        arg_31 = arg_30 - arg_29
                        for arg_32 in arg_31:
                            arg_33 = arg_27._links[arg_32].v_full_name
                            arg_28.f_add_link(arg_32, arg_33)

                return arg_23
            else:
                raise RuntimeError('You shall not pass!')
        except Exception:
            arg_0._is_run = arg_20


def Func(arg_0, arg_1):
        """Prepares the trajectory to explore the parameter space.

        To explore the parameter space you need to provide a dictionary with the names of the
        parameters to explore as keys and iterables specifying the exploration ranges as values.

        All iterables need to have the same length otherwise a ValueError is raised.
        A ValueError is also raised if the names from the dictionary map to groups or results
        and not parameters.

        If your trajectory is already explored but not stored yet and your parameters are
        not locked you can add new explored parameters to the current ones if their
        iterables match the current length of the trajectory.

        Raises an AttributeError if the names from the dictionary are not found at all in
        the trajectory and NotUniqueNodeError if the keys not unambiguously map
        to single parameters.

        Raises a TypeError if the trajectory has been stored already, please use
        :func:`~pypet.trajectory.Trajectory.f_expand` then instead.

        Example usage:

        >>> traj.Func({'groupA.param1' : [1,2,3,4,5], 'groupA.param2':['a','b','c','d','e']})

        Could also be called consecutively:

        >>> traj.Func({'groupA.param1' : [1,2,3,4,5]})
        >>> traj.Func({'groupA.param2':['a','b','c','d','e']})

        NOTE:

        Since parameters are very conservative regarding the data they accept
        (see :ref:`type_conservation`), you sometimes won't be able to use Numpy arrays
        for exploration as iterables.

        For instance, the following code snippet won't work:

        ::

            import numpy a np
            from pypet.trajectory import Trajectory
            traj = Trajectory()
            traj.f_add_parameter('my_float_parameter', 42.4,
                                 comment='My value is a standard python float')

            traj.Func( { 'my_float_parameter': np.arange(42.0, 44.876, 0.23) } )

        This will result in a `TypeError` because your exploration iterable
        `np.arange(42.0, 44.876, 0.23)` contains `numpy.float64` values
        whereas you parameter is supposed to use standard python floats.

        Yet, you can use Numpys `tolist()` function to overcome this problem:

        ::

            traj.Func( { 'my_float_parameter': np.arange(42.0, 44.876, 0.23).tolist() } )

        Or you could specify your parameter directly as a numpy float:

        ::

            traj.f_add_parameter('my_float_parameter', np.float64(42.4),
                                   comment='My value is a numpy 64 bit float')

        """
        for arg_2 in range(len(arg_0)):
            if arg_0.f_is_completed(arg_2):
                raise TypeError('You cannot explore a trajectory which has been explored before, '
                                'please use `f_expand` instead.')

        arg_3 = []
        try:
            arg_4 = len(arg_0)
            for arg_5, arg_6 in arg_1.items():
                arg_7 = arg_0.f_get(arg_5)
                if not arg_7.v_is_leaf or not arg_7.v_is_parameter:
                    raise ValueError('%s is not an appropriate search string for a parameter.' % arg_5)

                arg_7.f_unlock()

                arg_7._explore(arg_6)
                arg_3.append(arg_7)

                arg_8 = arg_7.v_full_name
                arg_0._explored_parameters[arg_8] = arg_7

                arg_7._explored = True

                # Compare the length of two consecutive parameters in the `build_dict`
                if len(arg_0._explored_parameters) == 1:
                    arg_4 = arg_7.f_get_range_length()
                elif not arg_4 == arg_7.f_get_range_length():
                    raise ValueError('The parameters to explore have not the same size!')

            for arg_11 in range(arg_4):
                arg_0._add_run_info(arg_11)
            arg_0._test_run_addition(arg_4)

        except Exception:
            # Remove the added parameters again
            for arg_12 in arg_3:
                arg_12.f_unlock()
                arg_12._shrink()
                arg_12._explored = False
                arg_8 = arg_12.v_full_name
                del arg_0._explored_parameters[arg_8]
            if len(arg_0._explored_parameters) == 0:
                arg_0.f_shrink(force=True)
            raise


def Func(arg_0, arg_1):
        """Overwrites the run information of a particular run"""
        arg_2 = arg_1['idx']
        arg_3 = arg_1['name']
        arg_0._run_information[arg_3] = arg_1
        arg_0._updated_run_information.add(arg_2)


def Func(arg_0):
        """Locks all non-empty parameters"""
        for arg_1 in arg_0._parameters.values():
            if not arg_1.f_is_empty():
                arg_1.f_lock()


def Func(arg_0):
        """Loads the full skeleton from the storage service.

        This needs to be done after a successful exploration in order to update the
        trajectory tree with all results and derived parameters from the individual single runs.
        This will only add empty results and derived parameters (i.e. the skeleton)
        and load annotations.

        """
        arg_0.f_load(arg_0.v_name, as_new=False, load_parameters=pypetconstants.LOAD_SKELETON,
                    load_derived_parameters=pypetconstants.LOAD_SKELETON,
                    load_results=pypetconstants.LOAD_SKELETON,
                    load_other_data=pypetconstants.LOAD_SKELETON,
                    with_run_information=False)


def Func(arg_0, arg_1=None, arg_2=None, arg_3=False, arg_4=arg_5.LOAD_DATA,
               arg_7=arg_5.LOAD_SKELETON,
               arg_9=arg_5.LOAD_SKELETON,
               arg_10=arg_5.LOAD_SKELETON,
               arg_11=True,
               arg_12=None,
               arg_13=None,
               arg_14=False,
               arg_15=None,
               arg_16=True,
               arg_17=True,
               arg_18=None, **arg_19):
        """Loads a trajectory via the storage service.

        If you want to load individual results or parameters manually, you can take
        a look at :func:`~pypet.trajectory.Trajectory.Func_items`.
        To only load subtrees check out :func:`~pypet.naturalnaming.NNGroupNode.Func_child`.

        For `Func` you can pass the following arguments:

        :param name:

            Name of the trajectory to be loaded. If no name or index is specified
            the current name of the trajectory is used.

        :param index:

            If you don't specify a name you can specify an integer index instead.
            The corresponding trajectory in the hdf5 file at the index
            position is loaded (counting starts with 0). Negative indices are also allowed
            counting in reverse order. For instance, `-1` refers to the last trajectory in
            the file, `-2` to the second last, and so on.

        :param as_new:

            Whether you want to rerun the experiments. So the trajectory is loaded only
            with parameters. The current trajectory name is kept in this case, which should be
            different from the trajectory name specified in the input parameter `name`.
            If you load `as_new=True` all parameters are unlocked.
            If you load `as_new=False` the current trajectory is replaced by the one on disk,
            i.e. name, timestamp, formatted time etc. are all taken from disk.

        :param load_parameters: How parameters and config items are loaded

        :param load_derived_parameters: How derived parameters are loaded

        :param load_results: How results are loaded

            You can specify how to load the parameters, derived parameters and results
            as follows:

                * :const:`pypet.pypetconstants.LOAD_NOTHING`: (0)

                    Nothing is loaded.

                * :const:`pypet.pypetconstants.LOAD_SKELETON`: (1)

                    The skeleton is loaded including annotations (See :ref:`more-on-annotations`).
                    This means that only empty
                    *parameter* and *result* objects will
                    be created  and you can manually load the data into them afterwards.
                    Note that :class:`pypet.annotations.Annotations` do not count as data and they
                    will be loaded because they are assumed to be small.

                * :const:`pypet.pypetconstants.LOAD_DATA`: (2)

                    The whole data is loaded. Note in case you have non-empty leaves
                    already in RAM, these are left untouched.

                * :const:`pypet.pypetconstants.OVERWRITE_DATA`: (3)

                    As before, but non-empty nodes are emptied and reloaded.

                Note that in all cases except :const:`pypet.pypetconstants.LOAD_NOTHING`,
                annotations will be reloaded if the corresponding instance
                is created or the annotations of an existing instance were emptied before.

        :param recursive:

            If data should be loaded recursively. If set to `None`, this is equivalent to
            set all data loading to `:const:`pypet.pypetconstants.LOAD_NOTHING`.

        :param load_data:

            As the above, per default set to `None`. If not `None` the setting of `load_data`
            will overwrite the settings of `load_parameters`, `load_derived_parameters`,
            `load_results`, and `load_other_data`. This is more or less or shortcut if all
            types should be loaded the same.

        :param max_depth:

            Maximum depth to load nodes (inclusive).

        :param force:

            *pypet* will refuse to load trajectories that have been created using *pypet* with a
            different version number or a different python version.
            To force the load of a trajectory from a previous version
            simply set ``force = True``. Note that it is not checked if other versions of packages
            differ from previous experiments, i.e. numpy, scipy, etc. But you can check
            for this manually. The versions of other packages can be found under
            ``'config.environment.name_of_environment.versions.package_name'``.

        :param dynamic_imports:

            If you've written a custom parameter that needs to be loaded dynamically
            during runtime, this needs to be specified here as a list of classes or
            strings naming classes and there module paths. For example:
            `dynamic_imports = ['pypet.parameter.PickleParameter',MyCustomParameter]`

            If you only have a single class to import, you do not need the list brackets:
            `dynamic_imports = 'pypet.parameter.PickleParameter'`

            The classes passed here are added for good and will be kept by the trajectory.
            Please add your dynamically imported classes only once.

        :param with_run_information:

            If information about the individual runs should be loaded. If you have many
            runs, like 1,000,000 or more you can spare time by setting
            `with_run_information=False`.
            Note that `f_get_run_information` and `f_idx_to_run` do not work in such a case.
            Moreover, setting `v_idx` does not work either. If you load the trajectory
            without this information, be careful, this is not recommended.

        :param wiht_meta_data:

            If meta data should be loaded.

        :param storage_service:

            Pass a storage service used by the trajectory. Alternatively pass a constructor
            and other ``**kwargs`` are passed onto the constructor. Leave `None` in combination
            with using no other kwargs, if you don't want to change the service
            the trajectory is currently using.

        :param kwargs:

            Other arguments passed to the storage service constructor. Don't pass any
            other kwargs and ``storage_service=None``,
            if you don't want to change the current service.

        """
        # Do some argument validity checks first
        if arg_1 is None and arg_2 is None:
            arg_1 = arg_0.v_name

        if arg_3:
            arg_4 = arg_5.LOAD_DATA
            arg_7 = arg_5.LOAD_NOTHING
            arg_9 = arg_5.LOAD_NOTHING
            arg_10 = arg_5.LOAD_NOTHING

        arg_20 = set(arg_19.keys())
        if arg_0.v_storage_service is None or arg_18 is not None or len(arg_19) > 0:
            arg_0._storage_service, arg_20 = storage_factory(arg_18=arg_18,
                                                                   trajectory=arg_0, **arg_19)
        if len(arg_20) > 0:
            raise ValueError('The following keyword arguments were not used: `%s`' %
                             str(arg_20))

        if arg_15 is not None:
            arg_0.f_add_to_dynamic_imports(arg_15)

        if arg_12 is not None:
            arg_4 = arg_12
            arg_7 = arg_12
            arg_9 = arg_12
            arg_10 = arg_12

        arg_0._storage_service.load(arg_5.TRAJECTORY, arg_0, trajectory_name=arg_1,
                                   trajectory_index=arg_2,
                                   arg_3=arg_3, arg_4=arg_4,
                                   arg_7=arg_7,
                                   arg_9=arg_9,
                                   arg_10=arg_10,
                                   arg_11=arg_11,
                                   arg_13=arg_13,
                                   arg_16=arg_16,
                                   arg_17=arg_17,
                                   arg_14=arg_14)

        # If a trajectory is newly loaded, all parameters are unlocked.
        if arg_3:
            for arg_22 in arg_0._parameters.values():
                arg_22.f_unlock()


def Func(arg_0, **arg_1):
        """Backs up the trajectory with the given storage service.

        Arguments of ``kwargs`` are directly passed to the storage service,
        for the HDF5StorageService you can provide the following argument:

        :param backup_filename:

            Name of file where to store the backup.

            In case you use the standard HDF5 storage service and `backup_filename=None`,
            the file will be chosen automatically.
            The backup file will be in the same folder as your hdf5 file and
            named 'backup_XXXXX.hdf5' where 'XXXXX' is the name of your current trajectory.

        """
        arg_0._storage_service.store(pypetconstants.BACKUP, arg_0, trajectory_name=arg_0.v_name,
                                    **arg_1)


def Func(arg_0, arg_1,
                arg_2=(),
                arg_3=False,
                arg_4=False,
                arg_5=True,
                arg_6=True,
                arg_7=True,
                arg_8=True):
        """Can be used to merge several `other_trajectories` into your current one.

        IMPORTANT `backup=True` only backs up the current trajectory not any of
        the `other_trajectories`. If you need a backup of these, do it manually.

        Parameters as for :func:`~pypet.trajectory.Trajectory.f_merge`.

        """
        arg_9 = len(arg_1)
        arg_0._logger.info('Merging %d trajectories into the current one.' % arg_9)
        arg_0.f_load_skeleton()

        if arg_8:
            arg_0.f_backup()

        for arg_10, arg_11 in enumerate(arg_1):
            arg_0.f_merge(arg_11, arg_2=arg_2,
                         arg_3=arg_3,
                         arg_4=arg_4,
                         arg_5=arg_5,
                         arg_6=arg_6,
                         arg_7=arg_7,
                         arg_8=False,
                         consecutive_merge=True)
            arg_0._logger.log(21,'Merged %d out of %d' % (arg_10 + 1, arg_9))
        arg_0._logger.info('Storing data to disk')
        arg_0._reversed_wildcards = {}
        arg_0.f_store()
        arg_0._logger.info('Finished final storage')


def Func(arg_0, arg_1, arg_2, arg_3=None, arg_4=None):
        """Renames a full name based on the wildcards and a particular run"""
        arg_5 = arg_1.split('.')
        for arg_6, arg_7 in enumerate(arg_5):
            if arg_7 in arg_2._reversed_wildcards:
                arg_8, arg_9 = arg_2._reversed_wildcards[arg_7]
                if arg_4 is None:
                    # We can safely take the first index of the index list that matches
                    arg_10 = None
                    for arg_11 in arg_8:
                        if arg_11 in arg_3:
                            arg_10 = arg_3[arg_11]
                            break
                        elif arg_11 == -1:
                            arg_10 = -1
                            break
                    if arg_10 is None:
                        raise RuntimeError('You shall not pass!')
                else:
                    arg_10 = arg_4
                arg_12 = arg_0.f_wildcard(arg_9[0], arg_10)
                arg_5[arg_6] = arg_12
        arg_1 = '.'.join(arg_5)
        return arg_1


def Func(arg_0,
                                    arg_1,
                                    arg_2,
                                    arg_3,
                                    arg_4,
                                    arg_5):
        """ Merges derived parameters that have the `run_ALL` in a name.

        Creates a new parameter with the name of the first new run and links to this
        parameter to avoid copying in all other runs.

        """
        arg_6 = arg_1._derived_parameters.copy()
        # get first run_idx
        arg_7 = min(arg_2.values())

        arg_8 = arg_1.f_wildcard('$', -1)
        for arg_9 in arg_6:
            if arg_9 in arg_5:
                continue
            arg_10 = arg_9.split('.')
            if not any(arg_11 in arg_8 for arg_11 in arg_10):
                continue
            arg_5.add(arg_9)

            arg_12 = arg_6[arg_9]
            arg_13 = arg_0._rename_full_name(arg_9, arg_1,
                                                    arg_2=arg_2)
            if arg_13 in arg_0:
                arg_14 = arg_0.f_get(arg_13, fast_access=False)
                if (arg_14._equal_values(arg_14.f_get(), arg_12.f_get()) and
                        not (arg_14.f_has_range() or arg_12.f_has_range())):
                    continue

            arg_15 = arg_0._rename_full_name(arg_9,
                                                          arg_1,
                                                          new_run_idx=arg_7)

            arg_3[arg_9] = arg_15
            arg_16 = arg_12.v_comment
            arg_17 = arg_12.f_get_class_name()
            arg_17 = arg_0._create_class(arg_17)
            arg_18 = arg_0.f_add_leaf(arg_17,
                                          arg_15,
                                          arg_16=arg_16)
            for arg_19 in arg_2.values():
                if arg_19 == arg_7:
                    continue
                arg_20 = arg_0._rename_full_name(arg_9, arg_1,
                                                    new_run_idx=arg_19)
                arg_10 = arg_20.split('.')
                arg_21 = arg_10.pop()
                arg_22 = '.'.join(arg_10)
                if not arg_0.f_contains(arg_22, shortcuts=False):
                    arg_23 = arg_0.f_add_group(arg_22)
                else:
                    arg_23 = arg_0.f_get(arg_22)

                arg_23.f_add_link(arg_21, arg_18)

        for arg_9 in arg_6:
            if arg_9 in arg_5:
                continue
            arg_10 = arg_9.split('.')
            arg_5.add(arg_9)
            if any(arg_11 in arg_1._reversed_wildcards and arg_11 not in arg_4
                        for arg_11 in arg_10):
                continue
            arg_24 = arg_0._rename_full_name(arg_9, arg_1,
                                                    arg_2=arg_2)
            if arg_0.f_contains(arg_24):
                arg_14 = arg_0.f_get(arg_24, fast_access=False)
                arg_12 = arg_6[arg_9]
                if (arg_14._equal_values(arg_14.f_get(), arg_12.f_get()) and
                        not (arg_14.f_has_range() or arg_12.f_has_range())):
                    continue
                else:
                    arg_0._logger.error('Could not merge parameter `%s`. '
                                       'I will ignore it!' % arg_24)
            arg_3[arg_9] = arg_24


def Func(arg_0, arg_1, arg_2, arg_3, arg_4):
        """ Merges all links"""
        arg_5 = arg_1._linked_by
        arg_6 = set([f(-1) for f in arg_1._wildcard_functions.values()])
        if len(arg_5) > 0:
            arg_0._logger.info('Merging potential links!')
            for arg_7 in arg_1._linked_by:
                if arg_7 in arg_4:
                    continue
                arg_8 = arg_7.split('.')
                if any(arg_9 in arg_6 for arg_9 in arg_8):
                    arg_0._logger.warning('Ignoring all links linking to `%s` because '
                                     'I don`t know how to resolve links under `%s` nodes.' %
                                     (arg_7, str(arg_6)))
                    continue
                arg_10 = arg_1._linked_by[arg_7]
                arg_8 = arg_7.split('.')
                if all(arg_9 in arg_3 for arg_9 in arg_8):
                    arg_11 = arg_0._rename_full_name(arg_7,
                                                                  arg_1,
                                                                  arg_2=arg_2)
                else:
                    arg_11 = arg_7

                for arg_12, arg_13 in arg_10.values():

                    arg_14 = arg_12.v_full_name
                    arg_8 = arg_14 .split('.')
                    if any(arg_9 in arg_6 for arg_9 in arg_8):
                        arg_0._logger.warning('Ignoring links under `%s` because '
                                             'I don`t know how to resolve links '
                                             'under a `%s` node.' %
                                             (arg_14, str(arg_6)))

                    arg_8 = arg_14 .split('.')
                    if any(arg_9 in arg_3 for arg_9 in arg_8):
                        arg_15 = arg_0._rename_full_name(arg_14,
                                                                      arg_1,
                                                                      arg_2=arg_2)
                    else:
                        arg_15 = arg_14

                    for arg_16 in arg_13:
                        if (arg_14 + '.' + arg_16) in arg_4:
                            continue
                        if arg_16 in arg_6:
                            arg_0._logger.warning('Ignoring link `%s` under `%s` because '
                                                 'I don`t know how to resolve '
                                                 'links named as `%s`.' %
                                                 (arg_16,
                                                  arg_14,
                                                  str(arg_6)))
                            continue

                        try:
                            arg_17 = arg_0.f_get(arg_11,
                                                         shortcuts=False)
                            if arg_0.f_contains(arg_15):
                                arg_18 = arg_0.f_get(arg_15,
                                                              shortcuts=False)
                            else:
                                arg_18 =  arg_0.f_add_group(arg_15)
                            if arg_16 in arg_3:
                                arg_19, arg_20 = arg_1._reversed_wildcards[arg_16]
                                arg_16 = arg_0.f_wildcard(arg_20[0], arg_2[arg_19[0]])
                            if not arg_16 in arg_18._links:
                                arg_18.f_add_link(arg_16, arg_17)
                            else:
                                arg_0._logger.debug('Link `%s` exists already under `%s`.' %
                                                    (arg_16, arg_17.v_full_name))
                        except (AttributeError, ValueError) as exc:
                            arg_0._logger.error('Could not copy link `%s` under `%s` linking '
                                               'to `%s` due to `%s`' %
                                               (arg_16, arg_14, arg_7,
                                                repr(exc)))


def Func(arg_0, arg_1):
        """Merges meta data about previous merges, git commits, and environment settings
        of the other trajectory into the current one.

        """
        arg_0._logger.info('Merging config!')

        # Merge git commit meta data
        if 'config.git' in arg_1:

            arg_0._logger.info('Merging git commits!')
            arg_2 = arg_1.f_get('config.git')
            arg_3 = []
            for arg_4 in arg_2.f_iter_leaves(with_links=False):
                if not arg_0.f_contains(arg_4.v_full_name, shortcuts=False):
                    arg_3.append(arg_0.f_add_config(arg_4))

            if arg_3:
                arg_0.f_store_items(arg_3)

            arg_0._logger.info('Merging git commits successful!')

        # Merge environment meta data
        if 'config.environment' in arg_1:

            arg_0._logger.info('Merging environment config!')
            arg_5 = arg_1.f_get('config.environment')
            arg_3 = []
            for arg_4 in arg_5.f_iter_leaves(with_links=False):
                if not arg_0.f_contains(arg_4.v_full_name, shortcuts=False):
                    arg_3.append(arg_0.f_add_config(arg_4))

            if arg_3:
                arg_0.f_store_items(arg_3)

            arg_0._logger.info('Merging config successful!')

        # Merge meta data of previous merges
        if 'config.merge' in arg_1:

            arg_0._logger.info('Merging merge config!')
            arg_6 = arg_1.f_get('config.merge')
            arg_3 = []
            for arg_4 in arg_6.f_iter_leaves(with_links=False):
                if not arg_0.f_contains(arg_4.v_full_name, shortcuts=False):
                    arg_3.append(arg_0.f_add_config(arg_4))

            if arg_3:
                arg_0.f_store_items(arg_3)

            arg_0._logger.info('Merging config successful!')


def Func(arg_0, arg_1, arg_2, arg_3, arg_4,
                       arg_5):
        """Merges all results.

        :param rename_dict:

            Dictionary that is filled with the names of results in the `other_trajectory`
            as keys and the corresponding new names in the current trajectory as values.
            Note for results kept under trajectory run branch there is actually no need to
            change the names. So we will simply keep the original name.

        """

        arg_6 = arg_1._results.copy()

        for arg_7 in arg_6:
            if arg_7 in arg_5:
                continue
            arg_8 = arg_7.split('.')
            arg_5.add(arg_7)
            if any(arg_9 in arg_1._reversed_wildcards and arg_9 not in arg_4
                        for arg_9 in arg_8):
                continue
            arg_10 = arg_0._rename_full_name(arg_7, arg_1,
                                                    arg_3=arg_3)
            if arg_0.f_contains(arg_10):
                arg_0._logger.warning('I found result `%s` already, I will ignore it.' % arg_10)
                continue
            arg_2[arg_7] = arg_10


def Func(arg_0, arg_1=None, arg_2=False,
                  arg_3=None, **arg_4):
        """Can be called to rename and relocate the trajectory.

        :param new_name: New name of the trajectory, None if you do not want to change the name.

        :param in_store:

            Set this to True if the trajectory has been stored with the new name at the new
            file before  and you just want to "switch back" to the location.
            If you migrate to a store used before and you do not set `in_store=True`,
            the storage service will throw a RuntimeError in case you store the Trajectory
            because it will assume that you try to store a new trajectory that accidentally has
            the very same name as another trajectory. If set to `True` and trajectory is not found
            in the file, the trajectory is simply stored to the file.

        :param new_storage_service:

            New service where you want to migrate to. Leave none if you want to keep the olde one.

        :param kwargs:

            Additional keyword arguments passed to the service.
            For instance, to change the file of the trajectory use ``filename='my_new_file.hdf5``.

        """
        if arg_1 is not None:
            arg_0._name = arg_1

        arg_6 = set(arg_4.keys())
        if arg_3 is not None or len(arg_4) > 0:
            arg_0._storage_service, arg_6 = storage_factory(
                                                    storage_service=arg_3,
                                                    trajectory=arg_0, **arg_4)
        if len(arg_6) > 0:
            raise ValueError('The following keyword arguments were not used: `%s`' %
                             str(arg_6))

        arg_0._stored = arg_2


def Func(arg_0):
        """ Restores the default value in all explored parameters and sets the
        v_idx property back to -1 and v_crun to None."""
        arg_0._idx = -1
        arg_0._crun = None
        for arg_3 in arg_0._explored_parameters.values():
            if arg_3 is not None:
                arg_3._restore_default()


def Func(arg_0, arg_1):
        """ Notifies the explored parameters what current point in the parameter space
        they should represent.

        """
        for arg_2 in arg_0._explored_parameters.values():
            if arg_2 is not None:
                arg_2._set_parameter_access(arg_1)


def Func(arg_0, arg_1=None, arg_2=True):
        """ Returns a dictionary containing information about a single run.

        ONLY useful during a single run if ``v_full_copy` was set to ``True``.
        Otherwise only the current run is available.

        The information dictionaries have the following key, value pairings:

            * completed: Boolean, whether a run was completed

            * idx: Index of a run

            * timestamp: Timestamp of the run as a float

            * time: Formatted time string

            * finish_timestamp: Timestamp of the finishing of the run

            * runtime: Total runtime of the run in human readable format

            * name: Name of the run

            * parameter_summary:

                A string summary of the explored parameter settings for the particular run

            * short_environment_hexsha: The short version of the environment SHA-1 code

        If no name or idx is given then a nested dictionary with keys as run names and
        info dictionaries as values is returned.

        :param name_or_idx: str or int

        :param copy:

            Whether you want the dictionary used by the trajectory or a copy. Note if
            you want the real thing, please do not modify it, i.e. popping or adding stuff. This
            could mess up your whole trajectory.

        :return:

            A run information dictionary or a nested dictionary of information dictionaries
            with the run names as keys.

        """
        if arg_1 is None:
            if arg_2:
                return cp.deepcopy(arg_0._run_information)
            else:
                return arg_0._run_information
        try:
            if arg_2:
                # Since the information dictionaries only contain immutable items
                # (float, int, str)
                # the normal copy operation is sufficient
                return arg_0._run_information[arg_1].copy()
            else:
                return arg_0._run_information[arg_1]
        except KeyError:
            # Maybe the user provided an idx, this would yield a key error and we
            # have to convert it to a run name
            arg_1 = arg_0.f_idx_to_run(arg_1)
            if arg_2:
                return arg_0._run_information[arg_1].copy()
            else:
                return arg_0._run_information[arg_1]