Instruction:
Can you generate a brief explanation for the following Python 3 code
def f_set_crun(self, name_or_idx):
        if (name_or_idx is None or name_or_idx == self.f_wildcard('$', -1) or
                    name_or_idx == -1):
            self.f_restore_default()
        else:
            if isinstance(name_or_idx, str):
                self._idx = self.f_idx_to_run(name_or_idx)
                self._crun = name_or_idx
            else:
                self._crun = self.f_idx_to_run(name_or_idx)
                self._idx = name_or_idx

            self._set_explored_parameters_to_idx(self.v_idx)

Response: Set the current run name for the given                   .


Instruction:
Can you generate the documentation for the following Python 3 function
def f_iter_runs(self, start=0, stop=None, step=1, yields='name'):
        if stop is None:
            stop =len(self)
        elif stop > len(self):
            raise ValueError('Stop cannot be larger than the trajectory lenght.')
        yields = yields.lower()
        if yields == 'name':
            yield_func = lambda x: self.f_idx_to_run(x)
        elif yields == 'idx':
            yield_func = lambda x: x
        elif yields == 'self':
            yield_func = lambda x: self
        elif yields == 'copy':
            yield_func = lambda x: self.__copy__()
        else:
            raise ValueError('Please choose yields among: `name`, `idx`, or `self`.')
        for idx in range(start, stop, step):
            self.f_set_crun(idx)
            yield yield_func(idx)

        self.f_set_crun(None)

Response: Makes the trajectory iterate over all runs.


Instruction:
Write a Python 3 script for
shrinking the trajectory and removes all exploration ranges from the run information.

Response:
def f_shrink(self, force=False):
        """ Shrinks the trajectory and removes all exploration ranges from the parameters.
        Only possible if the trajectory has not been stored to disk before or was loaded as new.

        :param force:

            Usually you cannot shrink the trajectory if it has been stored to disk,
            because there's no guarantee that it is actually shrunk if there
            still exist explored parameters on disk. In case you are certain that
            you did not store explored parameters to disk set or you deleted all
            of them from disk set `force=True`.

        :raises: TypeError if the trajectory was stored before.

        """
        if self._stored and not force:
            raise TypeError('Your trajectory is already stored to disk or database, shrinking is '
                            'not allowed.')

        for param in self._explored_parameters.values():
            param.f_unlock()
            try:
                param._shrink()
            except Exception as exc:
                self._logger.error('Could not shrink `%s` because of:`%s`' %
                                   (param.v_full_name, repr(exc)))

        # If we shrink, we do not have any explored parameters left and we can erase all
        # run information, and the length of the trajectory is 1 again.
        self._explored_parameters = {}
        self._run_information = {}
        self._single_run_ids = {}
        self._add_run_info(0)
        self._test_run_addition(1)


Instruction:
Can you generate the documentation for the following Python 3 function
def f_preset_config(self, config_name, *args, **kwargs):

        if not config_name.startswith('config.'):
            config_name = 'config.' + config_name

        self._preset(config_name, args, kwargs)

Response: Similar to func : ~pypet. trajectory. Trajectory. f_preset_parameter


Instruction:
Can you generate a brief explanation for the following Python 3 code
def f_preset_parameter(self, param_name, *args, **kwargs):

        if not param_name.startswith('parameters.'):
            param_name = 'parameters.' + param_name

        self._preset(param_name, args, kwargs)

Response: Presets the value of a parameter in the trajectory.


Instruction:
Implement a function in Python 3 to
call by the environment to make some initial configurations before performing the individual runs.

Response:
def _prepare_experiment(self):
        """Called by the environment to make some initial configurations before performing the
        individual runs.

        Checks if all parameters marked for presetting were preset. If not raises a
        DefaultReplacementError.

        Locks all parameters.

        Removal of potential results of previous runs in case the trajectory was expanded to avoid
        mixing up undesired shortcuts in natural naming.

        """
        if len(self._changed_default_parameters):
            raise pex.PresettingError(
                'The following parameters were supposed to replace a '
                'default value, but it was never tried to '
                'add default values with these names: %s' %
                str(self._changed_default_parameters))

        self.f_lock_parameters()
        self.f_lock_derived_parameters()


Instruction:
Can you write a function in Python 3 where it
searches for all occurrences of name in each run and returns a dictionary with the keys and values as keys and values as values.

Response:
def f_get_from_runs(self, name, include_default_run=True, use_indices=False,
                        fast_access=False, with_links = True,
                        shortcuts=True, max_depth=None, auto_load=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.f_get_from_runs(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.

        """
        result_dict = OrderedDict()
        old_crun = self.v_crun

        try:

            if len(self._run_parent_groups) > 0:
                for run_name in self.f_iter_runs():
                    # Iterate over all runs
                    value = None
                    already_found = False
                    for run_parent_group in self._run_parent_groups.values():
                        if run_name not in run_parent_group._children:
                            continue

                        try:
                            value = run_parent_group.f_get(run_name + '.' + name,
                                                           fast_access=False,
                                                           with_links=with_links,
                                                           shortcuts=shortcuts,
                                                           max_depth=max_depth,
                                                           auto_load=auto_load)
                            if already_found:
                                raise pex.NotUniqueNodeError('`%s` has been found several times '
                                                             'in one run.' % name)
                            else:
                                already_found = True

                        except (AttributeError, pex.DataNotInStorageError):
                            pass

                    if value is None and include_default_run:
                        for run_parent_group in self._run_parent_groups.values():
                            try:
                                value = run_parent_group.f_get(self.f_wildcard('$', -1) +
                                                               '.' + name,
                                                               fast_access=False,
                                                               with_links=with_links,
                                                               shortcuts=shortcuts,
                                                               max_depth=max_depth,
                                                               auto_load=auto_load)
                                if already_found:
                                    raise pex.NotUniqueNodeError('`%s` has been found several '
                                                                 'times in one run.' % name)
                                else:
                                    already_found = True
                            except (AttributeError, pex.DataNotInStorageError):
                                pass

                    if value is not None:

                        if value.v_is_leaf:
                            value = self._nn_interface._apply_fast_access(value, fast_access)

                        if use_indices:
                            key = self.f_idx_to_run(run_name)
                        else:
                            key = run_name

                        result_dict[key] = value

            return result_dict
        finally:
            self.v_crun = old_crun


Instruction:
Can you write a function in Python 3 where it
explores the trajectory and return the new trajectory with the expansion of the parameters.

Response:
def f_expand(self, build_dict, fail_safe=True):
        """Similar to :func:`~pypet.trajectory.Trajectory.f_explore`, but can be used to enlarge
        already completed trajectories.

        Please ensure before usage, that all explored parameters are loaded!

        :param build_dict:

            Dictionary containing the expansion

        :param fail_safe:

            If old ranges should be **deep-copied** in order to allow to restore
            the original exploration if something fails during expansion.
            Set to `False` if deep-copying your parameter ranges causes errors.

        :raises:

            TypeError: If not all explored parameters are enlarged

            AttributeError: If keys of dictionary cannot be found in the trajectory

            NotUniqueNodeError:

                If dictionary keys do not unambiguously map to single parameters

            ValueError: If not all explored parameter ranges are of the same length

        """
        if len(self._explored_parameters) == 0:
            self._logger.info('Your trajectory has not been explored, yet. '
                              'I will call `f_explore` instead.')
            return self.f_explore(build_dict)

        enlarge_set = set([self.f_get(key).v_full_name
                           for key in build_dict.keys()])

        # Check if all explored parameters will be enlarged, otherwise
        # We cannot enlarge the trajectory
        if not set(self._explored_parameters.keys()) == enlarge_set:
            raise TypeError('You have to enlarge dimensions you have explored before! Currently'
                            ' explored parameters are not the ones you specified in your building'
                            ' dictionary, i.e. %s != %s' %
                            (str(set(self._explored_parameters.keys())),
                             str(set(build_dict.keys()))))
        if any(x is None for x in self._explored_parameters.values()):
            raise TypeError('At least one of your explored parameters is not fully loaded, '
                            'please load it.')

        old_ranges = None
        if fail_safe:
            old_ranges = {}
            for param_name in self._explored_parameters:
                old_ranges[param_name] = self._explored_parameters[param_name].f_get_range()
            try:
                old_ranges = cp.deepcopy(old_ranges)
            except Exception:
                self._logger.error('Cannot deepcopy old parameter ranges, if '
                                     'something fails during `f_expand` I cannot revert the '
                                     'trajectory to old settings.')
                old_ranges = None

        try:
            count = 0
            length = None
            for key, builditerable in build_dict.items():
                act_param = self.f_get(key)

                act_param.f_unlock()
                act_param._expand(builditerable)

                name = act_param.v_full_name

                self._explored_parameters[name] = act_param

                # Compare the length of two consecutive parameters in the `build_dict`
                if count == 0:
                    length = act_param.f_get_range_length()
                elif not length == act_param.f_get_range_length():
                    raise ValueError('The parameters to explore have not the same size!')
                count += 1

            original_length = len(self)
            for irun in range(original_length, length):
                self._add_run_info(irun)
            self._test_run_addition(length)

            # We need to update the explored parameters in case they were stored:
            self._remove_exploration()

        except Exception:
            if old_ranges is not None:
                # Try to restore the original parameter exploration
                for param_name in old_ranges:
                    param_range = old_ranges[param_name]
                    param = self._explored_parameters[param_name]
                    param.f_unlock()
                    try:
                        param._shrink()
                    except Exception as exc:
                        self._logger.error('Could not shrink parameter `%s` '
                                           'because of:`%s`' % (param_name, repr(exc)))
                    param._explore(param_range)
                    param._explored = True
            raise


Instruction:
Can you generate the documentation for the following Python 3 function
def _remove_exploration(self):
        for param in self._explored_parameters.values():
            if param._stored:
                try:
                    self.f_delete_item(param)
                except Exception:
                    self._logger.exception('Could not delete expanded parameter `%s` '
                                           'from disk.' % param.v_full_name)

Response: Called if trajectory is expanded deletes all explored parameters from disk


Instruction:
How would you code a function in Python 3 to
return a shallow copy of the current trajectory.

Response:
def f_copy(self, copy_leaves=True,
                     with_links=True):
        """Returns a *shallow* copy of a trajectory.

        :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 with_links: If links should be ignored or followed and copied as well

        :return: A shallow copy

        """
        new_traj = Trajectory(_copy_traj=True)

        new_traj._length = self._length
        new_traj._name = self._name

        new_traj._timestamp = self._timestamp
        new_traj._time = self._time

        new_traj._single_run_ids = self._single_run_ids
        new_traj._run_information = self._run_information
        new_traj._updated_run_information = self._updated_run_information

        new_traj._fast_access = self._fast_access
        new_traj._shortcuts = self._shortcuts
        new_traj._iter_recursive = self._iter_recursive
        new_traj._max_depth = self._max_depth
        new_traj._auto_load = self._auto_load
        new_traj._with_links = self._with_links

        new_traj._environment_hexsha = self._environment_hexsha
        new_traj._environment_name = self._environment_name

        # Index of a trajectory is -1, if the trajectory should behave like a single run
        # and blind out other single run results, this can be changed via 'v_crun'.
        new_traj._idx = self._idx
        new_traj._crun = self._crun

        new_traj._standard_parameter = self._standard_parameter
        new_traj._standard_result = self._standard_result
        new_traj._standard_leaf = self._standard_leaf

        new_traj._auto_run_prepend = self._auto_run_prepend
        new_traj._no_clobber = self._no_clobber

        new_traj._run_started = self._run_started # For manually using a trajectory
        new_traj._run_by_environment = self._run_by_environment  # To disable manual running of experiment

        new_traj._full_copy = self._full_copy

        new_traj._dynamic_imports = self._dynamic_imports

        new_traj._wildcard_functions = self._wildcard_functions
        new_traj._wildcard_keys = self._wildcard_keys
        new_traj._reversed_wildcards = self._reversed_wildcards
        new_traj._wildcard_cache = self._wildcard_cache

        new_traj._comment = self._comment

        new_traj._stored = self._stored

        new_traj._storage_service = self._storage_service

        new_traj._is_run = self._is_run

        new_traj._copy_from(self, copy_leaves=copy_leaves,
                                   with_links=with_links)

        # Copy references to new nodes and leaves
        for my_dict, new_dict in ((self._new_nodes, new_traj._new_nodes),
                                 (self._new_links, new_traj._new_links)):
            for key in my_dict:
                value = my_dict[key]
                parent, child = value
                if parent is self:
                    new_parent = new_traj
                else:
                    new_parent = new_traj.f_get(parent.v_full_name,
                                            shortcuts=False,
                                            with_links=False,
                                            auto_load=False)
                new_child = new_parent._children[key[1]]
                new_dict[key] = (new_parent, new_child)

        return new_traj


Instruction:
Make a summary of the following Python 3 code
def _copy_from(self, node,
                          copy_leaves=True,
                          overwrite=False,
                          with_links=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(node_in, node_out):
            """Copies the skeleton of from `node_out` to `node_in`"""
            new_annotations = node_out.v_annotations
            node_in._annotations = new_annotations
            node_in.v_comment = node_out.v_comment

        def _add_leaf(leaf):
            """Adds a leaf to the trajectory"""
            leaf_full_name = leaf.v_full_name
            try:
                found_leaf = self.f_get(leaf_full_name,
                                        with_links=False,
                                        shortcuts=False,
                                        auto_load=False)
                if overwrite:
                    found_leaf.__setstate__(leaf.__getstate__())
                return found_leaf
            except AttributeError:
                pass
            if copy_leaves is True or (copy_leaves == 'explored' and
                                           leaf.v_is_parameter and leaf.v_explored):
                new_leaf = self.f_add_leaf(cp.copy(leaf))
            else:
                new_leaf = self.f_add_leaf(leaf)
            if new_leaf.v_is_parameter and new_leaf.v_explored:
                self._explored_parameters[new_leaf.v_full_name] = new_leaf
            return new_leaf

        def _add_group(group):
            """Adds a new group to the trajectory"""
            group_full_name = group.v_full_name
            try:
                found_group = self.f_get(group_full_name,
                                             with_links=False,
                                             shortcuts=False,
                                             auto_load=False)
                if overwrite:
                    _copy_skeleton(found_group, group)
                return found_group
            except AttributeError:
                pass
            new_group = self.f_add_group(group_full_name)
            _copy_skeleton(new_group, group)
            return new_group

        is_run = self._is_run
        self._is_run = False  # So that we can copy Config Groups and Config Data
        try:
            if node.v_is_leaf:
                return _add_leaf(node)
            elif node.v_is_group:
                other_root = node.v_root
                if other_root is self:
                    raise RuntimeError('You cannot copy a given tree to itself!')
                result = _add_group(node)
                nodes_iterator = node.f_iter_nodes(recursive=True, with_links=with_links)
                has_links = []
                if node._links:
                    has_links.append(node)
                for child in nodes_iterator:
                    if child.v_is_leaf:
                        _add_leaf(child)
                    else:
                        _add_group(child)
                        if child._links:
                            has_links.append(child)

                if with_links:
                    for current in has_links:
                        mine = self.f_get(current.v_full_name, with_links=False,
                                          shortcuts=False, auto_load=False)
                        my_link_set = set(mine._links.keys())
                        other_link_set = set(current._links.keys())
                        new_links = other_link_set - my_link_set
                        for link in new_links:
                            where_full_name = current._links[link].v_full_name
                            mine.f_add_link(link, where_full_name)

                return result
            else:
                raise RuntimeError('You shall not pass!')
        except Exception:
            self._is_run = is_run

Response: Copy a node from the current trajectory to the new trajectory.


Instruction:
Make a summary of the following Python 3 code
def f_explore(self, build_dict):
        for run_idx in range(len(self)):
            if self.f_is_completed(run_idx):
                raise TypeError('You cannot explore a trajectory which has been explored before, '
                                'please use `f_expand` instead.')

        added_explored_parameters = []
        try:
            length = len(self)
            for key, builditerable in build_dict.items():
                act_param = self.f_get(key)
                if not act_param.v_is_leaf or not act_param.v_is_parameter:
                    raise ValueError('%s is not an appropriate search string for a parameter.' % key)

                act_param.f_unlock()

                act_param._explore(builditerable)
                added_explored_parameters.append(act_param)

                full_name = act_param.v_full_name
                self._explored_parameters[full_name] = act_param

                act_param._explored = True

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

            for irun in range(length):
                self._add_run_info(irun)
            self._test_run_addition(length)

        except Exception:
            # Remove the added parameters again
            for param in added_explored_parameters:
                param.f_unlock()
                param._shrink()
                param._explored = False
                full_name = param.v_full_name
                del self._explored_parameters[full_name]
            if len(self._explored_parameters) == 0:
                self.f_shrink(force=True)
            raise

Response: Prepares the trajectory to explore the parameter space.


Instruction:
Can you tell what is the following Python 3 function doing
def _update_run_information(self, run_information_dict):
        idx = run_information_dict['idx']
        name = run_information_dict['name']
        self._run_information[name] = run_information_dict
        self._updated_run_information.add(idx)

Response: Updates the run information of a particular run


Instruction:
Can you tell what is the following Python 3 function doing
def _add_run_info(self, idx, name='', timestamp=42.0, finish_timestamp=1.337,
                      runtime='forever and ever', time='>>Maybe time`s gone on strike',
                      completed=0, parameter_summary='Not yet my friend!',
                      short_environment_hexsha='N/A'):
        """Adds a new run to the `_run_information` dict."""

        if idx in self._single_run_ids:
            # Delete old entries, they might be replaced by a new name
            old_name = self._single_run_ids[idx]
            del self._single_run_ids[old_name]
            del self._single_run_ids[idx]
            del self._run_information[old_name]

        if name == '':
            name = self.f_wildcard('$', idx)
        # The `_single_run_ids` dict is bidirectional and maps indices to run names and vice versa
        self._single_run_ids[name] = idx
        self._single_run_ids[idx] = name

        info_dict = {'idx': idx,
                     'timestamp': timestamp,
                     'finish_timestamp': finish_timestamp,
                     'runtime': runtime,
                     'time': time,
                     'completed': completed,
                     'name': name,
                     'parameter_summary': parameter_summary,
                     'short_environment_hexsha': short_environment_hexsha}

        self._run_information[name] = info_dict
        self._length = len(self._run_information)

Response: Adds a new run to the _run_information dict.


Instruction:
Can you tell what is the following Python 3 function doing
def f_lock_parameters(self):
        for par in self._parameters.values():
            if not par.f_is_empty():
                par.f_lock()

Response: Locks all non - empty parameters


Instruction:
Can you implement a function in Python 3 that
locks all non - empty derived parameters

Response:
def f_lock_derived_parameters(self):
        """Locks all non-empty derived parameters"""
        for par in self._derived_parameters.values():
            if not par.f_is_empty():
                par.f_lock()


Instruction:
Can you tell what is the following Python 3 function doing
def _finalize(self, store_meta_data=True):
        self._is_run = False
        self.f_set_crun(None)
        if store_meta_data:
            self.f_store(only_init=True)

Response:
Final rollback initiated by the environment

        Restores the trajectory as root of the tree, and stores meta data to disk.
        This updates the trajectory's information about single runs, i.e. if they've been
        completed, when they were started, etc.


Instruction:
Given the following Python 3 function, write the documentation
def f_load_skeleton(self):
        self.f_load(self.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)

Response: Loads the full skeleton from the storage service.


Instruction:
Write a Python 3 function for
loading a trajectory from the hdf5 file.

Response:
def f_load(self, name=None, index=None, as_new=False, load_parameters=pypetconstants.LOAD_DATA,
               load_derived_parameters=pypetconstants.LOAD_SKELETON,
               load_results=pypetconstants.LOAD_SKELETON,
               load_other_data=pypetconstants.LOAD_SKELETON,
               recursive=True,
               load_data=None,
               max_depth=None,
               force=False,
               dynamic_imports=None,
               with_run_information=True,
               with_meta_data=True,
               storage_service=None, **kwargs):
        """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.f_load_items`.
        To only load subtrees check out :func:`~pypet.naturalnaming.NNGroupNode.f_load_child`.

        For `f_load` 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 name is None and index is None:
            name = self.v_name

        if as_new:
            load_parameters = pypetconstants.LOAD_DATA
            load_derived_parameters = pypetconstants.LOAD_NOTHING
            load_results = pypetconstants.LOAD_NOTHING
            load_other_data = pypetconstants.LOAD_NOTHING

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

        if dynamic_imports is not None:
            self.f_add_to_dynamic_imports(dynamic_imports)

        if load_data is not None:
            load_parameters = load_data
            load_derived_parameters = load_data
            load_results = load_data
            load_other_data = load_data

        self._storage_service.load(pypetconstants.TRAJECTORY, self, trajectory_name=name,
                                   trajectory_index=index,
                                   as_new=as_new, load_parameters=load_parameters,
                                   load_derived_parameters=load_derived_parameters,
                                   load_results=load_results,
                                   load_other_data=load_other_data,
                                   recursive=recursive,
                                   max_depth=max_depth,
                                   with_run_information=with_run_information,
                                   with_meta_data=with_meta_data,
                                   force=force)

        # If a trajectory is newly loaded, all parameters are unlocked.
        if as_new:
            for param in self._parameters.values():
                param.f_unlock()


Instruction:
Write a Python 3 script for
checking if two trajectories live in the same space and can be merged.

Response:
def _check_if_both_have_same_parameters(self, other_trajectory,
                                            ignore_data, consecutive_merge):
        """ Checks if two trajectories live in the same space and can be merged. """

        if not isinstance(other_trajectory, Trajectory):
            raise TypeError('Can only merge trajectories, the other trajectory'
                            ' is of type `%s`.' % str(type(other_trajectory)))

        if self._stored and not consecutive_merge:
            self.f_load_skeleton()
        if other_trajectory._stored:
            other_trajectory.f_load_skeleton()

        # Check wildcard set
        other_wildcard_set = set(x[1] for x in other_trajectory._wildcard_functions.keys())
        wildcard_set = set(x[1] for x in self._wildcard_functions.keys())
        diff = wildcard_set.symmetric_difference(other_wildcard_set)
        if diff:
            raise TypeError('The wildcard sets are not matching. `%s` != `%s`' %
                            (str(wildcard_set), str(other_wildcard_set)))

        # Load all parameters of the current and the other trajectory
        if self._stored:
            # To suppress warnings if nothing needs to be loaded
            with self._nn_interface._disable_logging:
                self.f_load_items(self._parameters.keys(), only_empties=True)
        if other_trajectory._stored:
            with self._nn_interface._disable_logging:
                other_trajectory.f_load_items(other_trajectory._parameters.keys(),
                                              only_empties=True)

        self.f_restore_default()
        other_trajectory.f_restore_default()

        allmyparams = self._parameters.copy()
        allotherparams = other_trajectory._parameters.copy()

        # If not ignored, add also the trajectory derived parameters to check for merging
        if 'derived_parameters' in self:
            my_traj_dpars = self._derived_parameters
            if self._stored:
                with self._nn_interface._disable_logging:
                    self.f_load_items(my_traj_dpars.keys(), only_empties=True)
            allmyparams.update(my_traj_dpars)
            other_traj_dpars = other_trajectory._derived_parameters
            if other_trajectory._stored:
                with self._nn_interface._disable_logging:
                    other_trajectory.f_load_items(other_traj_dpars.keys(), only_empties=True)
            allotherparams.update(other_traj_dpars)

        # Check if the trajectories have the same parameters:
        my_keyset = set(allmyparams.keys())
        other_keyset = set(allotherparams.keys())
        diff = my_keyset.symmetric_difference(other_keyset) - ignore_data
        run_dummys = (self.f_wildcard('$', -1), other_trajectory.f_wildcard('$', -1))
        if diff:
            run_difference_can_be_resolved = True
            for full_name in diff:
                split_name = full_name.split('.')
                if not any(x in self._run_information or
                                x in other_trajectory._run_information or
                                    x in run_dummys
                                        for x in split_name):
                    run_difference_can_be_resolved = False
                    break
                elif full_name in allotherparams:
                    del allotherparams[full_name]
            if not run_difference_can_be_resolved:
                raise TypeError('Cannot merge trajectories, '
                                'they do not live in the same space,the '
                                'set of parameters `%s` is only '
                                'found in one trajectory.' % str(diff))

        # Check if corresponding parameters in both trajectories are of the same type
        for key, other_param in allotherparams.items():
            if key in ignore_data:
                continue
            my_param = self.f_get(key)
            split_key = key.split('.')
            if any(x in self._run_information or
                        x in other_trajectory._run_information
                            for x in split_key):
                pass
            else:
                if not my_param._values_of_same_type(my_param.f_get(), other_param.f_get()):
                    raise TypeError('Cannot merge trajectories, values of parameters `%s` are not '
                                    'of the same type. Types are %s (current) and %s (other).' %
                                    (key, str(type(my_param.f_get())),
                                     str(type(other_param.f_get()))))


Instruction:
Can you generate a brief explanation for the following Python 3 code
def f_backup(self, **kwargs):
        self._storage_service.store(pypetconstants.BACKUP, self, trajectory_name=self.v_name,
                                    **kwargs)

Response: Backs up the current trajectory with the given storage service.


Instruction:
How would you explain what the following Python 3 function does
def _make_reversed_wildcards(self, old_length=-1):
        if len(self._reversed_wildcards) > 0:
            # We already created reversed wildcards, so we don't need to do all of them
            # again
            start = old_length
        else:
            start = -1
        for wildcards, func in self._wildcard_functions.items():
            for irun in range(start, len(self)):
                translated_name = func(irun)
                if not translated_name in self._reversed_wildcards:
                    self._reversed_wildcards[translated_name] = ([], wildcards)
                self._reversed_wildcards[translated_name][0].append(irun)

Response: Creates a full mapping from all wildcard translations to the corresponding wildcards


Instruction:
Can you tell what is the following Python 3 function doing
def f_merge_many(self, other_trajectories,
                ignore_data=(),
                move_data=False,
                delete_other_trajectory=False,
                keep_info=True,
                keep_other_trajectory_info=True,
                merge_config=True,
                backup=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`.

        """
        other_length = len(other_trajectories)
        self._logger.info('Merging %d trajectories into the current one.' % other_length)
        self.f_load_skeleton()

        if backup:
            self.f_backup()

        for idx, other in enumerate(other_trajectories):
            self.f_merge(other, ignore_data=ignore_data,
                         move_data=move_data,
                         delete_other_trajectory=delete_other_trajectory,
                         keep_info=keep_info,
                         keep_other_trajectory_info=keep_other_trajectory_info,
                         merge_config=merge_config,
                         backup=False,
                         consecutive_merge=True)
            self._logger.log(21,'Merged %d out of %d' % (idx + 1, other_length))
        self._logger.info('Storing data to disk')
        self._reversed_wildcards = {}
        self.f_store()
        self._logger.info('Finished final storage')

Response: This function merges two trajectories into the current trajectory.


Instruction:
Can you tell what is the following Python 3 function doing
def f_merge(self, other_trajectory, trial_parameter=None, remove_duplicates=False,
                ignore_data=(),
                backup=True,
                move_data=False,
                delete_other_trajectory=False,
                keep_info=True,
                keep_other_trajectory_info=True,
                merge_config=True,
                consecutive_merge=False,
                slow_merge=False):
        """Merges another trajectory into the current trajectory.

        Both trajectories must live in the same space. This means both need to have the same
        parameters with similar types of values.

        Note that links are also merged. There are exceptions: Links found under
        a generic run group called `run_ALL` or links linking to a node under such a
        group are NOT merged and simply skipped, because there is no straightforward
        way to resolve the link.

        :param other_trajectory: Other trajectory instance to merge into the current one.

        :param trial_parameter:

            If you have a particular parameter that specifies only the trial
            number, i.e. an integer parameter running form 0 to T1 and
            0 to T2, the parameter is modified such that after merging it will
            cover the range 0 to T1+T2+1. T1 is the number of individual trials in the current
            trajectory and T2 number of trials in the other trajectory.

        :param remove_duplicates:

            Whether you want to remove duplicate parameter points.
            Requires N1 * N2 (quadratic complexity in single runs).
            A ValueError is raised if no runs would be merged.

        :param ignore_data:

            List of full names of data that should be ignored and not merged.

        :param backup:

            If ``True``, backs up both trajectories into files chosen automatically
            by the storage services. If you want to customize your backup use
            the `f_backup` function instead.

        :param move_data:

           Tells the storage service to move data from one trajectory to the other
           instead of copying it.

           If you use the HDF5 storage service and both trajectories are
           stored in the same file, merging is performed fast directly within
           the file. You can choose if you want to copy nodes ('move_nodes=False`)
           from the other trajectory to the current one, or if you want to move them.
           Accordingly, the stored data is no longer accessible in the other trajectory.

        :param delete_other_trajectory:

            If you want to delete the other trajectory after merging.

        :param keep_info:

            If `True`, information about the merge is added to the trajectory `config` tree under
            `config.merge`.

        :param merge_config:

            Whether or not to merge all config parameters under `.config.git`,
            `.config.environment`, and `.config.merge` of the other trajectory
            into the current one.

        :param keep_other_trajectory_info:

            Whether to keep information like length, name, etc. of the other trajectory
            in case you want to keep all the information. Setting of `keep_other_trajectory_info`
            is irrelevant in case `keep_info=False`.

        :param consecutive_merge:
            Can be set to `True` if you are about to merge several trajectories into the current
            one within a loop to avoid quadratic complexity.
            But remember to store your trajectory manually after
            all merges. Also make sure that all parameters and derived parameters are available
            in your current trajectory and load them before the consecutive merging.
            Also avoid specifying a `trial_parameter` and set `backup=False`
            to avoid quadratic complexity in case of consecutive merges.

        :param slow_merge:
            Enforces a slow merging. This means all data is loaded one after the other to
            memory and stored to disk. Otherwise it is tried to directly copy the data
            from one file into another without explicitly loading the data.

        If you cannot directly merge trajectories within one HDF5 file, a slow merging process
        is used. Results are loaded, stored, and emptied again one after the other. Might take
        some time!

        Annotations of parameters and derived parameters under `.derived_parameters.trajectory`
        are NOT merged. If you wish to extract the annotations of these parameters you have to
        do that manually before merging. Note that annotations of results and derived parameters
        of single runs are copied, so you don't have to worry about these.

        """
        if consecutive_merge and trial_parameter is not None:
            self._logger.warning('If you do a consecutive merge and specify a trial parameter, '
                                 'your merging will still suffer from quadratic time complexity!')
        if consecutive_merge and backup:
            self._logger.warning('If you do a consecutive merge and backup, '
                                 'your merging will still suffer from quadratic time complexity!')

        # Keep the timestamp of the merge
        timestamp = time.time()
        original_ignore_data = set(ignore_data)
        ignore_data = original_ignore_data.copy()

        old_len = len(self)

        # Check if trajectories can be merged
        self._check_if_both_have_same_parameters(other_trajectory, ignore_data, consecutive_merge)

        # Create a full mapping set for renaming
        self._make_reversed_wildcards(old_length=old_len)
        other_trajectory._make_reversed_wildcards()

        # BACKUP if merge is possible
        if backup:
            other_trajectory.f_backup()
            self.f_backup()

        # Merge parameters and keep track which runs where used and which parameters need
        # to be updated
        self._logger.info('Merging the parameters')
        used_runs, changed_parameters = self._merge_parameters(
            other_trajectory,
            remove_duplicates,
            trial_parameter,
            ignore_data)

        ignore_data.update(set(changed_parameters))

        if len(used_runs) == 0:
            raise ValueError('Your merge discards all runs of the other trajectory, maybe you '
                             'try to merge a trajectory with itself?')

        # Dictionary containing the mappings between run names in the other trajectory
        # and their new names in the current trajectory
        rename_dict = {}

        self._logger.info('Merging run information')
        allowed_translations = set([translation for translation, pair in
                                    other_trajectory._reversed_wildcards.items() if
                                        any(x in used_runs for x in pair[0])])
        self._merge_single_runs(other_trajectory, used_runs)

        self._logger.info('Merging derived parameters')
        self._merge_derived_parameters(other_trajectory=other_trajectory,
                                         used_runs=used_runs,
                                         rename_dict=rename_dict,
                                         allowed_translations=allowed_translations,
                                         ignore_data=ignore_data)

        # Keep track of all trajectory results that should be merged and put
        # information into `rename_dict`
        self._merge_results(other_trajectory=other_trajectory,
                             used_runs=used_runs,
                             rename_dict=rename_dict,
                             allowed_translations=allowed_translations,
                             ignore_data=ignore_data)

        # The storage service needs to prepare the file for merging.
        # This includes updating meta information and already storing the merged parameters
        self._logger.info('Start copying results and single run derived parameters')
        self._logger.info('Updating Trajectory information and changed parameters in storage')
        self._storage_service.store(pypetconstants.PREPARE_MERGE, self,
                                    trajectory_name=self.v_name,
                                    changed_parameters=changed_parameters,
                                    old_length=old_len)

        if not slow_merge:
            try:
                # Merge the single run derived parameters and all results
                # within the same hdf5 file based on `renamed_dict`
                try:
                    # try to get the other file
                    other_filename = other_trajectory.v_storage_service.filename
                except AttributeError:
                    self._logger.warning('Could not determine the filename of the other '
                                         'trajectory, I will assume it`s in the same file.')
                    other_filename = None
                self._storage_service.store(pypetconstants.MERGE, 'FAST MERGE', trajectory_name=self.v_name,
                                            other_trajectory_name=other_trajectory.v_name,
                                            rename_dict=rename_dict, move_nodes=move_data,
                                            delete_trajectory=delete_other_trajectory,
                                            other_filename=other_filename)

            except pex.NoSuchServiceError as exc:
                # If the storage service does not support merge we end up here
                self._logger.exception('My storage service does not support merging of trajectories, '
                                     'I will use the f_load mechanism of the other trajectory and '
                                     'store the results slowly item by item. '
                                     'Note that thereby the other '
                                     'trajectory will be altered (in RAM).')
                slow_merge = True

            except ValueError as exc:
                # If both trajectories are stored in separate files we end up here
                self._logger.exception('Could not perfom fast merging. '
                                     'I will use the `f_load` method of the other trajectory and '
                                     'store the results slowly item by item. '
                                     'Note that thereby the other '
                                     'trajectory will be altered (in RAM).')
                slow_merge = True

        if slow_merge:
            self._merge_slowly(other_trajectory, rename_dict)

        # We will merge the git commits and other config data
        if merge_config:
            self._merge_config(other_trajectory)

        # Finally merging links
        self._merge_links(other_trajectory=other_trajectory,
                         used_runs=used_runs,
                         allowed_translations=allowed_translations,
                         ignore_data=original_ignore_data)

        # Add meta information about the merge to the current trajectory
        self._logger.info('Adding merge information')
        formatted_time = datetime.datetime.fromtimestamp(timestamp).strftime('%Y_%m_%d_%Hh%Mm%Ss')
        hexsha = hashlib.sha1((self.v_name +
                                             str(self.v_timestamp) +
                                             other_trajectory.v_name +
                                             str(other_trajectory.v_timestamp) +
                                             VERSION).encode('utf-8')).hexdigest()

        short_hexsha = hexsha[0:7]

        if keep_info:
            merge_name = 'merge_%s_%s' % (short_hexsha, formatted_time)

            config_name = 'merge.%s.merged_runs' % merge_name
            self.f_add_config(config_name, len(used_runs),
                              comment='Number of merged runs')

            config_name = 'merge.%s.timestamp' % merge_name
            self.f_add_config(config_name, timestamp,
                              comment='Timestamp of merge')

            config_name = 'merge.%s.hexsha' % merge_name
            self.f_add_config(config_name, hexsha,
                              comment='SHA-1 identifier of the merge')

            config_name = 'merge.%s.remove_duplicates' % merge_name
            self.f_add_config(config_name, remove_duplicates,
                              comment='Option to remove duplicate entries')

            if original_ignore_data:
                config_name = 'merge.%s.ignore_data' % merge_name
                self.f_add_config(config_name, tuple(original_ignore_data),
                                  comment='Data to ignore during merge')

            config_name = 'merge.%s.length_before_merge' % merge_name
            self.f_add_config(config_name, len(self),
                              comment='Length of trajectory before merge')

            self.config.merge.v_comment = 'Settings and information of the different merges'

            if self.v_version != VERSION:
                config_name = 'merge.%s.version' % merge_name
                self.f_add_config(config_name, self.v_version,
                                  comment='Pypet version if it differs from the version'
                                          ' of the trajectory')

            if trial_parameter is not None:
                config_name = 'merge.%s.trial_parameter' % merge_name
                self.f_add_config(config_name, len(other_trajectory),
                                  comment='Name of trial parameter')

            if keep_other_trajectory_info:

                if other_trajectory.v_version != self.v_version:
                    config_name = 'merge.%s.other_trajectory.version' % merge_name
                    self.f_add_config(config_name, other_trajectory.v_version,
                                      comment='The version of pypet you used to manage the other'
                                              ' trajectory. Only added if other trajectory\'s'
                                              ' version differs from current trajectory version.')

                config_name = 'merge.%s.other_trajectory.name' % merge_name
                self.f_add_config(config_name, other_trajectory.v_name,
                                  comment='Name of other trajectory merged into the current one')

                config_name = 'merge.%s.other_trajectory.timestamp' % merge_name
                self.f_add_config(config_name, other_trajectory.v_timestamp,
                                  comment='Timestamp of creation of other trajectory '
                                          'merged into the current one')

                config_name = 'merge.%s.other_trajectory.length' % merge_name
                self.f_add_config(config_name, len(other_trajectory),
                                  comment='Length of other trajectory')

                if other_trajectory.v_comment:
                    config_name = 'merge.%s.other_trajectory.comment' % merge_name
                    self.f_add_config(config_name, other_trajectory.v_comment,
                                      comment='Comment of other trajectory')

        # Write out the merged data to disk
        if not consecutive_merge:
            self._logger.info('Writing merged data to disk')
            self.f_store(store_data=pypetconstants.STORE_DATA)
            self._reversed_wildcards = {}
        other_trajectory._reversed_wildcards = {}

        self._logger.info('Finished Merging!')

Response: Merges another trajectory into the current trajectory.


Instruction:
Can you generate the documentation for the following Python 3 function
def _merge_single_runs(self, other_trajectory, used_runs):
        count = len(self)  # Variable to count the increasing new run indices and create
        # new run names

        run_indices = range(len(other_trajectory))

        run_name_dict = OrderedDict()

        to_store_groups_with_annotations = []

        for idx in run_indices:
            # Iterate through all used runs and store annotated groups and mark results and
            # derived parameters for merging
            if idx in used_runs:
                # Update the run information dict of the current trajectory
                other_info_dict = other_trajectory.f_get_run_information(idx)
                time_ = other_info_dict['time']
                timestamp = other_info_dict['timestamp']
                completed = other_info_dict['completed']
                short_environment_hexsha = other_info_dict['short_environment_hexsha']
                finish_timestamp = other_info_dict['finish_timestamp']
                runtime = other_info_dict['runtime']

                new_idx = used_runs[idx]
                new_runname = self.f_wildcard('$', new_idx)

                run_name_dict[idx] = new_runname

                info_dict = dict(
                    idx=new_idx,
                    time=time_,
                    timestamp=timestamp,
                    completed=completed,
                    short_environment_hexsha=short_environment_hexsha,
                    finish_timestamp=finish_timestamp,
                    runtime=runtime)

                self._add_run_info(**info_dict)

Response: Updates the run information dict of the current trajectory with the run information of the other trajectory.


Instruction:
Make a summary of the following Python 3 code
def _rename_full_name(self, full_name, other_trajectory, used_runs=None, new_run_idx=None):
        split_name = full_name.split('.')
        for idx, name in enumerate(split_name):
            if name in other_trajectory._reversed_wildcards:
                run_indices, wildcards = other_trajectory._reversed_wildcards[name]
                if new_run_idx is None:
                    # We can safely take the first index of the index list that matches
                    run_idx = None
                    for run_jdx in run_indices:
                        if run_jdx in used_runs:
                            run_idx = used_runs[run_jdx]
                            break
                        elif run_jdx == -1:
                            run_idx = -1
                            break
                    if run_idx is None:
                        raise RuntimeError('You shall not pass!')
                else:
                    run_idx = new_run_idx
                new_name = self.f_wildcard(wildcards[0], run_idx)
                split_name[idx] = new_name
        full_name = '.'.join(split_name)
        return full_name

Response: Renames a full name based on the wildcards and a particular run


Instruction:
Given the following Python 3 function, write the documentation
def _merge_derived_parameters(self,
                                    other_trajectory,
                                    used_runs,
                                    rename_dict,
                                    allowed_translations,
                                    ignore_data):
        """ 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.

        """
        other_derived_parameters = other_trajectory._derived_parameters.copy()
        # get first run_idx
        new_first_run_idx = min(used_runs.values())

        run_name_dummy = other_trajectory.f_wildcard('$', -1)
        for param_name in other_derived_parameters:
            if param_name in ignore_data:
                continue
            split_name = param_name.split('.')
            if not any(x in run_name_dummy for x in split_name):
                continue
            ignore_data.add(param_name)

            param = other_derived_parameters[param_name]
            new_param_name = self._rename_full_name(param_name, other_trajectory,
                                                    used_runs=used_runs)
            if new_param_name in self:
                my_param = self.f_get(new_param_name, fast_access=False)
                if (my_param._equal_values(my_param.f_get(), param.f_get()) and
                        not (my_param.f_has_range() or param.f_has_range())):
                    continue

            first_new_param_name = self._rename_full_name(param_name,
                                                          other_trajectory,
                                                          new_run_idx=new_first_run_idx)

            rename_dict[param_name] = first_new_param_name
            comment = param.v_comment
            param_type = param.f_get_class_name()
            param_type = self._create_class(param_type)
            first_param = self.f_add_leaf(param_type,
                                          first_new_param_name,
                                          comment=comment)
            for run_idx in used_runs.values():
                if run_idx == new_first_run_idx:
                    continue
                next_name = self._rename_full_name(param_name, other_trajectory,
                                                    new_run_idx=run_idx)
                split_name = next_name.split('.')
                link_name = split_name.pop()
                location_name = '.'.join(split_name)
                if not self.f_contains(location_name, shortcuts=False):
                    the_group = self.f_add_group(location_name)
                else:
                    the_group = self.f_get(location_name)

                the_group.f_add_link(link_name, first_param)

        for param_name in other_derived_parameters:
            if param_name in ignore_data:
                continue
            split_name = param_name.split('.')
            ignore_data.add(param_name)
            if any(x in other_trajectory._reversed_wildcards and x not in allowed_translations
                        for x in split_name):
                continue
            new_name = self._rename_full_name(param_name, other_trajectory,
                                                    used_runs=used_runs)
            if self.f_contains(new_name):
                my_param = self.f_get(new_name, fast_access=False)
                param = other_derived_parameters[param_name]
                if (my_param._equal_values(my_param.f_get(), param.f_get()) and
                        not (my_param.f_has_range() or param.f_has_range())):
                    continue
                else:
                    self._logger.error('Could not merge parameter `%s`. '
                                       'I will ignore it!' % new_name)
            rename_dict[param_name] = new_name

Response: Merges derived parameters that have the run_ALL flag set.


Instruction:
Create a Python 3 function to
merge all links in the other_trajectory with the current one.

Response:
def _merge_links(self, other_trajectory, used_runs, allowed_translations, ignore_data):
        """ Merges all links"""
        linked_items = other_trajectory._linked_by
        run_name_dummys = set([f(-1) for f in other_trajectory._wildcard_functions.values()])
        if len(linked_items) > 0:
            self._logger.info('Merging potential links!')
            for old_linked_name in other_trajectory._linked_by:
                if old_linked_name in ignore_data:
                    continue
                split_name = old_linked_name.split('.')
                if any(x in run_name_dummys for x in split_name):
                    self._logger.warning('Ignoring all links linking to `%s` because '
                                     'I don`t know how to resolve links under `%s` nodes.' %
                                     (old_linked_name, str(run_name_dummys)))
                    continue
                old_link_dict = other_trajectory._linked_by[old_linked_name]
                split_name = old_linked_name.split('.')
                if all(x in allowed_translations for x in split_name):
                    new_linked_full_name = self._rename_full_name(old_linked_name,
                                                                  other_trajectory,
                                                                  used_runs=used_runs)
                else:
                    new_linked_full_name = old_linked_name

                for linking_node, link_set in old_link_dict.values():

                    linking_full_name = linking_node.v_full_name
                    split_name = linking_full_name .split('.')
                    if any(x in run_name_dummys for x in split_name):
                        self._logger.warning('Ignoring links under `%s` because '
                                             'I don`t know how to resolve links '
                                             'under a `%s` node.' %
                                             (linking_full_name, str(run_name_dummys)))

                    split_name = linking_full_name .split('.')
                    if any(x in allowed_translations for x in split_name):
                        new_linking_full_name = self._rename_full_name(linking_full_name,
                                                                      other_trajectory,
                                                                      used_runs=used_runs)
                    else:
                        new_linking_full_name = linking_full_name

                    for link in link_set:
                        if (linking_full_name + '.' + link) in ignore_data:
                            continue
                        if link in run_name_dummys:
                            self._logger.warning('Ignoring link `%s` under `%s` because '
                                                 'I don`t know how to resolve '
                                                 'links named as `%s`.' %
                                                 (link,
                                                  linking_full_name,
                                                  str(run_name_dummys)))
                            continue

                        try:
                            new_linked_item = self.f_get(new_linked_full_name,
                                                         shortcuts=False)
                            if self.f_contains(new_linking_full_name):
                                new_linking_item = self.f_get(new_linking_full_name,
                                                              shortcuts=False)
                            else:
                                new_linking_item =  self.f_add_group(new_linking_full_name)
                            if link in allowed_translations:
                                run_indices, wildcards = other_trajectory._reversed_wildcards[link]
                                link = self.f_wildcard(wildcards[0], used_runs[run_indices[0]])
                            if not link in new_linking_item._links:
                                new_linking_item.f_add_link(link, new_linked_item)
                            else:
                                self._logger.debug('Link `%s` exists already under `%s`.' %
                                                    (link, new_linked_item.v_full_name))
                        except (AttributeError, ValueError) as exc:
                            self._logger.error('Could not copy link `%s` under `%s` linking '
                                               'to `%s` due to `%s`' %
                                               (link, linking_full_name, old_linked_name,
                                                repr(exc)))


Instruction:
How would you explain what the following Python 3 function does
def _merge_config(self, other_trajectory):
        self._logger.info('Merging config!')

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

            self._logger.info('Merging git commits!')
            git_node = other_trajectory.f_get('config.git')
            param_list = []
            for param in git_node.f_iter_leaves(with_links=False):
                if not self.f_contains(param.v_full_name, shortcuts=False):
                    param_list.append(self.f_add_config(param))

            if param_list:
                self.f_store_items(param_list)

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

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

            self._logger.info('Merging environment config!')
            env_node = other_trajectory.f_get('config.environment')
            param_list = []
            for param in env_node.f_iter_leaves(with_links=False):
                if not self.f_contains(param.v_full_name, shortcuts=False):
                    param_list.append(self.f_add_config(param))

            if param_list:
                self.f_store_items(param_list)

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

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

            self._logger.info('Merging merge config!')
            merge_node = other_trajectory.f_get('config.merge')
            param_list = []
            for param in merge_node.f_iter_leaves(with_links=False):
                if not self.f_contains(param.v_full_name, shortcuts=False):
                    param_list.append(self.f_add_config(param))

            if param_list:
                self.f_store_items(param_list)

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

Response: Merges the config of the current trajectory into the other trajectory.


Instruction:
Can you generate the documentation for the following Python 3 function
def _merge_slowly(self, other_trajectory, rename_dict):
        for other_key in rename_dict:
            new_key = rename_dict[other_key]

            other_instance = other_trajectory.f_get(other_key)

            if other_instance.f_is_empty():
                # To suppress warnings if nothing needs to be loaded
                with self._nn_interface._disable_logging:
                    other_trajectory.f_load_item(other_instance)

            if not self.f_contains(new_key):
                class_name = other_instance.f_get_class_name()
                class_ = self._create_class(class_name)
                my_instance = self.f_add_leaf(class_, new_key)
            else:
                my_instance = self.f_get(new_key, shortcuts=False)

            if not my_instance.f_is_empty():
                raise RuntimeError('Something is wrong! Your item `%s` should be empty.' % new_key)

            load_dict = other_instance._store()
            my_instance._load(load_dict)
            my_instance.f_set_annotations(**other_instance.v_annotations.f_to_dict(copy=False))
            my_instance.v_comment = other_instance.v_comment

            self.f_store_item(my_instance)

            # We do not want to blow up the RAM Memory
            if other_instance.v_is_parameter:
                other_instance.f_unlock()
                my_instance.f_unlock()
            other_instance.f_empty()
            my_instance.f_empty()

Response: Merges trajectories by loading iteratively items of the other trajectory and store them into the current trajectory.


Instruction:
Make a summary of the following Python 3 code
def _merge_results(self, other_trajectory, rename_dict, used_runs, allowed_translations,
                       ignore_data):
        """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.

        """

        other_results = other_trajectory._results.copy()

        for result_name in other_results:
            if result_name in ignore_data:
                continue
            split_name = result_name.split('.')
            ignore_data.add(result_name)
            if any(x in other_trajectory._reversed_wildcards and x not in allowed_translations
                        for x in split_name):
                continue
            new_name = self._rename_full_name(result_name, other_trajectory,
                                                    used_runs=used_runs)
            if self.f_contains(new_name):
                self._logger.warning('I found result `%s` already, I will ignore it.' % new_name)
                continue
            rename_dict[result_name] = new_name

Response: Merges all results in the current trajectory with the other trajectory.


Instruction:
Given the following Python 3 function, write the documentation
def _merge_parameters(self, other_trajectory, remove_duplicates=False,
                          trial_parameter_name=None,
                          ignore_data=()):
        """Merges parameters from the other trajectory into the current one.

        The explored parameters in the current trajectory are directly enlarged (in RAM),
        no storage service is needed here. Later on in `f_merge` the storage service
        will be requested to store the enlarge parameters to disk.

        Note explored parameters are always enlarged. Unexplored parameters might become
        new explored parameters if they differ in their default values
        in the current and the other trajectory, respectively.

        :return: A tuple with two elements:

            1.

                Dictionary of run index mappings from old trajectroy to the new one.

            2.

                List of names of parameters that were altered.

        """

        if trial_parameter_name:
            if remove_duplicates:
                self._logger.warning('You have given a trial parameter and you want to '
                                     'remove_items duplicates. There cannot be any duplicates '
                                     'when adding trials, I will not look for duplicates.')
                remove_duplicates = False

        # Dictionary containing full parameter names as keys
        # and pairs of parameters from both trajectories as values.
        # Parameters kept in this dictionary are marked for merging and will be enlarged
        # with ranges and values of corresponding parameters in the other trajectory
        params_to_change = {}

        if trial_parameter_name:
            # We want to merge a trial parameter
            # First make some sanity checks
            my_trial_parameter = self.f_get(trial_parameter_name)
            other_trial_parameter = other_trajectory.f_get(trial_parameter_name)
            if not isinstance(my_trial_parameter, BaseParameter):
                raise TypeError('Your trial_parameter `%s` does not evaluate to a real parameter'
                                ' in the trajectory' % trial_parameter_name)

            # Extract the ranges of both trial parameters
            if my_trial_parameter.f_has_range():
                my_trial_list = my_trial_parameter.f_get_range(copy=False)
            else:
                # If we only have a single trial, we need to make a range of length 1
                # This is probably a very exceptional case
                my_trial_list = [my_trial_parameter.f_get()]

            if other_trial_parameter.f_has_range():
                other_trial_list = other_trial_parameter.f_get_range(copy=False)
            else:
                other_trial_list = [other_trial_parameter.f_get()]

            # Make sanity checks if both ranges contain all numbers from 0 to T1
            # for the current trajectory and 0 to T2 for the other trajectory
            mytrialset = set(my_trial_list)
            mymaxtrial_T1 = max(mytrialset)  # maximum trial index in current trajectory aka T1

            if mytrialset != set(range(mymaxtrial_T1 + 1)):
                raise TypeError('In order to specify a trial parameter, this parameter must '
                                'contain integers from 0 to %d, but it in fact it '
                                'contains `%s`.' % (mymaxtrial_T1, str(mytrialset)))

            othertrialset = set(other_trial_list)
            othermaxtrial_T2 = max(othertrialset)  # maximum trial index in other trajectory aka T2
            if othertrialset != set(range(othermaxtrial_T2 + 1)):
                raise TypeError('In order to specify a trial parameter, this parameter must '
                                'contain integers from 0 to %d, but it infact it contains `%s` '
                                'in the other trajectory.' %
                                (othermaxtrial_T2, str(othertrialset)))

            # If the trial parameter's name was just given in parts we update it here
            # to the full name
            trial_parameter_name = my_trial_parameter.v_full_name

            # If we had the very exceptional case, that our trial parameter was not explored,
            # aka we only had 1 trial, we have to add it to the explored parameters
            if not trial_parameter_name in self._explored_parameters:
                self._explored_parameters[trial_parameter_name] = my_trial_parameter

            # We need to mark the trial parameter for merging
            params_to_change[trial_parameter_name] = (my_trial_parameter, other_trial_parameter)

        # Dictionary containing all parameters of the other trajectory, we will iterate through it
        # to spot parameters that need to be enlarge or become new explored parameters
        params_to_merge = other_trajectory._parameters.copy()

        params_to_merge.update(other_trajectory._derived_parameters)
        for ignore in ignore_data:
            if ignore in params_to_merge:
                del params_to_merge[ignore]

        run_name_dummys = set([f(-1) for f in other_trajectory._wildcard_functions.values()])
        # Iterate through all parameters of the other trajectory
        # and check which differ from the parameters of the current trajectory
        for key in params_to_merge:
            other_param = params_to_merge[key]

            # We don't need to merge anything based on wildcards
            split_key = key.split('.')
            if any(x in other_trajectory._reversed_wildcards for x in split_key):
                continue

            my_param = self.f_get(key)
            if not my_param._values_of_same_type(my_param.f_get(), other_param.f_get()):
                raise TypeError('The parameters with name `%s` are not of the same type, cannot '
                                'merge trajectory.' % key)

            # We have taken care about the trial parameter before, it is already
            # marked for merging
            if my_param.v_full_name == trial_parameter_name:
                continue

            # If a parameter was explored in one of the trajectories or two unexplored
            # parameters differ, we need to mark them for merge
            if (my_param.f_has_range() or
                    other_param.f_has_range() or
                    not my_param._equal_values(my_param.f_get(), other_param.f_get())):

                # If two unexplored parameters differ, that means they differ in every run,
                # accordingly we do not need to check for duplicate runs anymore
                params_to_change[key] = (my_param, other_param)
                if not my_param.f_has_range() and not other_param.f_has_range():
                    remove_duplicates = False

        # Check if we use all runs or remove duplicates:
        used_runs = {}
        for idx in range(len(other_trajectory)):
            used_runs[idx] = idx
        if remove_duplicates:

            # We need to compare all parameter combinations in the current trajectory
            # to all parameter combinations in the other trajectory to spot duplicate points.
            # Quadratic Complexity!
            for irun in range(len(other_trajectory)):
                for jrun in range(len(self)):
                    change = True

                    # Check all marked parameters
                    for my_param, other_param in params_to_change.values():
                        if other_param.f_has_range():
                            other_param._set_parameter_access(irun)

                        if my_param.f_has_range():
                            my_param._set_parameter_access(jrun)

                        val1 = my_param.f_get()
                        val2 = other_param.f_get()

                        # If only one parameter differs, the parameter space point differs
                        # and we can skip the rest of the parameters
                        if not my_param._equal_values(val1, val2):
                            change = False
                            break

                    # If we found one parameter space point in the current trajectory
                    # that matches the ith point in the other, we do not need the ith
                    # point. We can also skip comparing to the rest of the points in the
                    # current trajectory
                    if change:
                        del used_runs[irun]
                        break

            # Restore changed default values
            for my_param, other_param in params_to_change.values():
                other_param._restore_default()
                my_param._restore_default()

        # Merge parameters into the current trajectory
        adding_length = len(used_runs)
        starting_length = len(self)
        if adding_length == 0:
            return used_runs, []
        count = 0
        for key in sorted(used_runs.keys()):
            used_runs[key] = starting_length + count
            count += 1

        for my_param, other_param in params_to_change.values():
            fullname = my_param.v_full_name

            # We need new ranges to enlarge all parameters marked for merging
            if fullname == trial_parameter_name:
                # The trial parameter now has to cover the range 0 to T1+T2+1
                other_range = [x + mymaxtrial_T1 + 1 for x in other_trial_list]
            else:
                # In case we do not use all runs we need to filter the ranges of the
                # parameters of the other trajectory
                if other_param.f_has_range():
                    other_range = (x for jdx, x in enumerate(other_param.f_get_range(copy=False))
                                                             if jdx in used_runs)
                else:
                    other_range = (other_param.f_get() for _ in range(adding_length))

            # If a parameter in the current trajectory was marked for merging but was not
            # explored before, we need to explore it first, simply by creating the range of
            # the current trajectory's length containing only it's default value
            if not my_param.f_has_range():
                my_param.f_unlock()
                my_param._explore((my_param.f_get() for _ in  range(len(self))))

            # After determining the new range extension `other_range`,
            # expand the parameters
            my_param.f_unlock()
            my_param._expand(other_range)

            if not fullname in self._explored_parameters:
                self._explored_parameters[fullname] = my_param

        return used_runs, list(params_to_change.keys())

Response: Merges parameters from the current trajectory into the other trajectory.


Instruction:
Can you create a Python 3 function that
stores the trajectory to disk and recursively all data in the tree.

Response:
def f_store(self, only_init=False, store_data=pypetconstants.STORE_DATA,
                max_depth=None):
        """ Stores the trajectory to disk and recursively all data in the tree.

        :param only_init:

            If you just want to initialise the store. If yes, only meta information about
            the trajectory is stored and none of the groups/leaves within the trajectory.
            Alternatively, you can pass `recursive=False`.

        :param store_data:

            Only considered if ``only_init=False``. Choose of the following:

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

                    Nothing is store.

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

                    Speedy version of normal ``STORE_DATA`` will entirely skip groups
                    (but not their children) and leaves if they have been stored before.
                    No new data is added in this case.

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

                    Stores every group and leave node. If they contain data that is not yet stored
                    to disk it is added.

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

                    Stores all groups and leave nodes and will delete all data on disk
                    and overwrite it with the current data in RAM.

                    **NOT RECOMMENDED**! Overwriting data on disk fragments the HDF5 file and
                    yields badly compressed large files. Better stick to the concept
                    write once and read many!

        If you use the HDF5 Storage Service usually (STORE_DATA (2)) only novel data
        is stored to disk.
        If you have results that have been stored to disk before only new data items are added and
        already present data is NOT overwritten.

        Overwriting (OVERWRITE_DATA (3)) existing data with the HDF5 storage service
        is not recommended due to fragmentation of the HDF5 file. Better stick to the concept
        write once, but read often.

        If you want to store individual parameters or results, you might want to
        take a look at :func:`~pypet.Trajectory.f_store_items`.
        To store whole subtrees of your trajectory check out
        :func:`~pypet.naturalnaming.NNGroupNode.f_store_child`.
        Note both functions require that your trajectory was stored to disk with `f_store`
        at least once before.

        **ATTENTION**: Calling `f_store` during a single run the behavior is different.

        To avoid re-storing the full trajectory in every single run, which is redundant,
        only sub-trees of the trajectory are really stored.

        The storage serivce looks for new data that is added below groups called `run_XXXXXXXXXX`
        and stores it where `XXXXXXXXX` is the index of this run. The `only_init` parameter is
        ignored in this case. You can avoid this behavior by using the argument from below.

        :param max_depth:

            Maximum depth to store tree (inclusive). During single runs `max_depth` is also counted
            from root.

        """
        if self._is_run:
            if self._new_nodes or self._new_links:
                self._storage_service.store(pypetconstants.SINGLE_RUN, self,
                                        trajectory_name=self.v_name,
                                        recursive=not only_init,
                                        store_data=store_data,
                                        max_depth=max_depth)
        else:
            self._storage_service.store(pypetconstants.TRAJECTORY, self,
                                        trajectory_name=self.v_name,
                                        only_init=only_init,
                                        store_data=store_data,
                                        max_depth=max_depth)

            self._stored = True


Instruction:
How would you explain what the following Python 3 function does
def f_is_empty(self):
        return (len(self._parameters) == 0 and
                len(self._derived_parameters) == 0 and
                len(self._results) == 0 and
                len(self._other_leaves) == 0)

Response: Whether the trajectory contains no results nor derived parameters.


Instruction:
Can you generate the documentation for the following Python 3 function
def f_restore_default(self):
        self._idx = -1
        self._crun = None
        for param in self._explored_parameters.values():
            if param is not None:
                param._restore_default()

Response:
Restores the default value in all explored parameters and sets the
        v_idx property to - 1 and v_crun to None.


Instruction:
Implement a function in Python 3 to
set the index of the explored parameters to the index idx.

Response:
def _set_explored_parameters_to_idx(self, idx):
        """ Notifies the explored parameters what current point in the parameter space
        they should represent.

        """
        for param in self._explored_parameters.values():
            if param is not None:
                param._set_parameter_access(idx)


Instruction:
Can you tell what is the following Python 3 function doing
def _make_single_run(self):
        self._is_run = False # to be able to use f_set_crun
        self._new_nodes = OrderedDict()
        self._new_links = OrderedDict()
        self._is_run = True
        return self

Response: Modifies the trajectory for single runs executed by the environment


Instruction:
Write a Python 3 function for
returning a list of run names.

Response:
def f_get_run_names(self, sort=True):
        """ Returns a list of run names.

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

        :param sort:

            Whether to get them sorted, will only require O(N) [and not O(N*log N)] since we
            use (sort of) bucket sort.

        """
        if sort:
            return [self.f_idx_to_run(idx) for idx in range(len(self))]
        else:
            return list(self._run_information.keys())


Instruction:
Implement a function in Python 3 to
return a dictionary containing information about a single run.

Response:
def f_get_run_information(self, name_or_idx=None, copy=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 name_or_idx is None:
            if copy:
                return cp.deepcopy(self._run_information)
            else:
                return self._run_information
        try:
            if copy:
                # Since the information dictionaries only contain immutable items
                # (float, int, str)
                # the normal copy operation is sufficient
                return self._run_information[name_or_idx].copy()
            else:
                return self._run_information[name_or_idx]
        except KeyError:
            # Maybe the user provided an idx, this would yield a key error and we
            # have to convert it to a run name
            name_or_idx = self.f_idx_to_run(name_or_idx)
            if copy:
                return self._run_information[name_or_idx].copy()
            else:
                return self._run_information[name_or_idx]