def _prm_read_table(self, table_or_group, full_name):
        """Reads a non-nested PyTables table column by column and created a new ObjectTable for
        the loaded data.

        :param table_or_group:

            PyTables table to read from or a group containing subtables.

        :param full_name:

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

        :return:

            Data to be loaded

        """
        try:
            result_table = None

            if self._all_get_from_attrs(table_or_group, HDF5StorageService.SPLIT_TABLE):
                table_name = table_or_group._v_name

                data_type_table_name = table_name + '__' + HDF5StorageService.STORAGE_TYPE

                data_type_table = table_or_group._v_children[data_type_table_name]
                data_type_dict = {}

                for row in data_type_table:
                    fieldname = row['field_name'].decode('utf-8')
                    data_type_dict[fieldname] = row['data_type'].decode('utf-8')

                for sub_table in table_or_group:
                    sub_table_name = sub_table._v_name

                    if sub_table_name == data_type_table_name:
                        continue

                    for colname in sub_table.colnames:
                        # Read Data column by column
                        col = sub_table.col(colname)
                        data_list = list(col)

                        prefix = HDF5StorageService.FORMATTED_COLUMN_PREFIX % colname
                        for idx, data in enumerate(data_list):
                            # Recall original type of data
                            data, type_changed = self._all_recall_native_type(data,
                                                                              PTItemMock(
                                                                                data_type_dict),
                                                                              prefix)
                            if type_changed:
                                data_list[idx] = data
                            else:
                                break

                        # Construct or insert into an ObjectTable
                        if result_table is None:
                            result_table = ObjectTable(data={colname: data_list})
                        else:
                            result_table[colname] = data_list

            else:
                for colname in table_or_group.colnames:
                    # Read Data column by column
                    col = table_or_group.col(colname)
                    data_list = list(col)

                    prefix = HDF5StorageService.FORMATTED_COLUMN_PREFIX % colname
                    for idx, data in enumerate(data_list):
                        # Recall original type of data
                        data, type_changed = self._all_recall_native_type(data, table_or_group,
                                                                          prefix)
                        if type_changed:
                            data_list[idx] = data
                        else:
                            break

                    # Construct or insert into an ObjectTable
                    if result_table is None:
                        result_table = ObjectTable(data={colname: data_list})
                    else:
                        result_table[colname] = data_list

            return result_table
        except:
            self._logger.error(
                'Failed loading `%s` of `%s`.' % (table_or_group._v_name, full_name))
            raise

Reads a non - nested PyTables table column by column and created a new ObjectTable for the loaded data .


def _prm_read_array(self, array, full_name):
        """Reads data from an array or carray

        :param array:

            PyTables array or carray to read from

        :param full_name:

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

        :return:

            Data to load

        """
        try:
            result = self._svrc_read_array(array)
            # Recall original data types
            result, dummy = self._all_recall_native_type(result, array,
                                                         HDF5StorageService.DATA_PREFIX)

            return result
        except:
            self._logger.error('Failed loading `%s` of `%s`.' % (array._v_name, full_name))
            raise

def
_prm_read_array
(
self
,
array
,
full_name
)
:
try
:
result
=
self
.
_svrc_read_array
(
array
)
# Recall original data types
result
,
dummy
=
self
.
_all_recall_native_type
(
result
,
array
,
HDF5StorageService
.
DATA_PREFIX
)
return
result
except
:
self
.
_logger
.
error
(
'Failed loading `%s` of `%s`.'
%
(
array
.
_v_name
,
full_name
)
)
raise


def load_trajectory(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,
                    new_name='my_trajectory',
                    add_time=True,
                    wildcard_functions=None,
                    with_run_information=True,
                    storage_service=storage.HDF5StorageService,
                    **kwargs):
    """Helper function that creates a novel trajectory and loads it from disk.

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

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

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

    traj = Trajectory(name=new_name, add_time=add_time, dynamic_imports=dynamic_imports,
                      wildcard_functions=wildcard_functions)
    traj.f_load(name=name, 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, load_data=load_data,
                max_depth=max_depth, force=force, with_run_information=with_run_information,
                storage_service=storage_service, **kwargs)
    return traj

Helper function that creates a novel trajectory and loads it from disk .


def make_set_name(idx):
    """Creates a run set name based on ``idx``"""
    GROUPSIZE = 1000
    set_idx = idx // GROUPSIZE
    if set_idx >= 0:
        return pypetconstants.FORMATTED_SET_NAME % set_idx
    else:
        return pypetconstants.SET_NAME_DUMMY

def make_set_name ( idx ) : GROUPSIZE = 1000 set_idx = idx // GROUPSIZE if set_idx >= 0 : return pypetconstants . FORMATTED_SET_NAME % set_idx else : return pypetconstants . SET_NAME_DUMMY


def f_set_properties(self, **kwargs):
        """Sets properties like ``v_fast_access``.

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

        """
        for name in kwargs:
            val = kwargs[name]
            if not name.startswith('v_'):
                name = 'v_' + name
            if not name in self._nn_interface._not_admissible_names:
                raise AttributeError('Cannot set property `%s` does not exist.' % name)
            else:
                setattr(self, name, val)


def f_add_to_dynamic_imports(self, dynamic_imports):
        """Adds classes or paths to classes to the trajectory to create custom parameters.

        :param dynamic_imports:

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

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

        """

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

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

        self._dynamic_imports.extend(dynamic_imports)

Adds classes or paths to classes to the trajectory to create custom parameters .


def f_set_crun(self, name_or_idx):
        """Can make the trajectory behave as during a particular single run.

        It allows easier data analysis.

         Has the following effects:

        *
            `v_idx` and `v_crun` are set to the appropriate index and run name

        *
            All explored parameters are set to the corresponding value in the exploration
            ranges, i.e. when you call :func:`~pypet.parameter.Parameter.f_get` (or fast access)
            on them you will get in return the value at the corresponding `v_idx` position
            in the exploration range.

        *
            If you perform a search in the trajectory tree, the trajectory will
            only search the run subtree under *results* and *derived_parameters* with the
            corresponding index.
            For instance, if you use `f_set_crun('run_00000007')` or `f_set_crun(7)`
            and search for `traj.results.z` this will search for `z` only in the subtree
            `traj.results.run_00000007`. Yet, you can still explicitly name other subtrees,
            i.e. `traj.results.run_00000004.z` will still work.

        """
        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)

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 )

Can make the trajectory behave as during a particular single run .


def f_iter_runs(self, start=0, stop=None, step=1, yields='name'):
        """Makes the trajectory iterate over all runs.

        :param start: Start index of run

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

        :param step: Stepsize

        :param yields:

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

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

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

        Thus, the following code snippet

        ::

            for run_name in traj.f_iter_runs():

                 # Do some stuff here...

        is equivalent to

        ::

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

                # Do some stuff here...

            traj.f_set_crun(None)

        :return:

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

        """
        if 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)

Makes the trajectory iterate over all runs .


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)

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 .


def _preset(self, name, args, kwargs):
        """Generic preset function, marks a parameter or config for presetting."""
        if self.f_contains(name, shortcuts=False):
            raise ValueError('Parameter `%s` is already part of your trajectory, use the normal'
                             'accessing routine to change config.' % name)
        else:
            self._changed_default_parameters[name] = (args, kwargs)

Generic preset function marks a parameter or config for presetting .


def f_preset_parameter(self, param_name, *args, **kwargs):
        """Presets parameter value before a parameter is added.

        Can be called before parameters are added to the Trajectory in order to change the
        values that are stored into the parameter on creation.

        After creation of a parameter, the instance of the parameter is called
        with `param.f_set(*args,**kwargs)` with `*args`, and `**kwargs` provided by the user
        with `f_preset_parameter`.

        Before an experiment is carried out it is checked if all parameters that were
        marked were also preset.

        :param param_name:

            The full name (!) of the parameter that is to be changed after its creation.

        :param args:

            Arguments that will be used for changing the parameter's data

        :param kwargs:

            Keyword arguments that will be used for changing the parameter's data

        Example:

        >>> traj.f_preset_parameter('groupA.param1', data=44)
        >>> traj.f_add_parameter('groupA.param1', data=11)
        >>> traj.parameters.groupA.param1
        44

        """

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

        self._preset(param_name, args, kwargs)

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 )

Presets parameter value before a parameter is added .


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()

Called by the environment to make some initial configurations before performing the individual runs .


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

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

Searches for all occurrences of name in each run .


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

        if name_or_id is None:
            return all(
                (runinfo['completed'] for runinfo in self._run_information.values()))
        else:
            return self.f_get_run_information(name_or_id, copy=False)['completed']

def _is_completed ( self , name_or_id = None ) : if name_or_id is None : return all ( ( runinfo [ 'completed' ] for runinfo in self . _run_information . values ( ) ) ) else : return self . f_get_run_information ( name_or_id , copy = False ) [ 'completed' ]


def _remove_exploration(self):
        """ Called if trajectory is expanded, deletes all explored parameters from disk """
        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)

Called if trajectory is expanded deletes all explored parameters from disk


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

Pass a node to insert the full tree to the trajectory .


def f_explore(self, build_dict):
        """Prepares the trajectory to explore the parameter space.

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

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

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

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

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

        Example usage:

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

        Could also be called consecutively:

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

        NOTE:

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

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

        ::

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

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

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

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

        ::

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

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

        ::

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

        """
        for 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

Prepares the trajectory to explore the parameter space .


def _update_run_information(self, run_information_dict):
        """Overwrites the run information of a particular run"""
        idx = run_information_dict['idx']
        name = run_information_dict['name']
        self._run_information[name] = run_information_dict
        self._updated_run_information.add(idx)

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 )


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)

Adds a new run to the _run_information dict .


def f_lock_parameters(self):
        """Locks all non-empty parameters"""
        for par in self._parameters.values():
            if not par.f_is_empty():
                par.f_lock()

def f_lock_parameters ( self ) : for par in self . _parameters . values ( ) : if not par . f_is_empty ( ) : par . f_lock ( )


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()

def f_lock_derived_parameters ( self ) : for par in self . _derived_parameters . values ( ) : if not par . f_is_empty ( ) : par . f_lock ( )

Locks all non - empty derived parameters


def _finalize(self, store_meta_data=True):
        """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.

        """
        self._is_run = False
        self.f_set_crun(None)
        if store_meta_data:
            self.f_store(only_init=True)

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 )


def f_load_skeleton(self):
        """Loads the full skeleton from the storage service.

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

        """
        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)

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 )

Loads the full skeleton from the storage service .


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()

Loads a trajectory via the storage service .


def f_backup(self, **kwargs):
        """Backs up the trajectory with the given storage service.

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

        :param backup_filename:

            Name of file where to store the backup.

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

        """
        self._storage_service.store(pypetconstants.BACKUP, self, trajectory_name=self.v_name,
                                    **kwargs)

def f_backup ( self , * * kwargs ) : self . _storage_service . store ( pypetconstants . BACKUP , self , trajectory_name = self . v_name , * * kwargs )

Backs up the trajectory with the given storage service .


def _make_reversed_wildcards(self, old_length=-1):
        """Creates a full mapping from all wildcard translations to the corresponding wildcards"""
        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)


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')

Can be used to merge several other_trajectories into your current one .


def _merge_single_runs(self, other_trajectory, used_runs):
        """  Updates the `run_information` of the current trajectory."""
        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)

Updates the run_information of the current trajectory .


def _rename_full_name(self, full_name, other_trajectory, used_runs=None, new_run_idx=None):
        """Renames a full name based on the wildcards and a particular run"""
        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


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

def
_merge_derived_parameters
(
self
,
other_trajectory
,
used_runs
,
rename_dict
,
allowed_translations
,
ignore_data
)
:
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

Merges derived parameters that have the run_ALL in a name .


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)))


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

        """
        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!')

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!'
)

Merges meta data about previous merges git commits and environment settings of the other trajectory into the current one .


def _merge_slowly(self, other_trajectory, rename_dict):
        """Merges trajectories by loading iteratively items of the other trajectory and
        store it into the current trajectory.

        :param rename_dict:

            Dictionary containing mappings from the old result names in the `other_trajectory`
            to the new names in the current trajectory.

        """
        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()

Merges trajectories by loading iteratively items of the other trajectory and store it into the current trajectory .


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


def f_migrate(self, new_name=None, in_store=False,
                  new_storage_service=None, **kwargs):
        """Can be called to rename and relocate the trajectory.

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

        :param in_store:

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

        :param new_storage_service:

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

        :param kwargs:

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

        """
        if new_name is not None:
            self._name = new_name

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

        self._stored = in_store

Can be called to rename and relocate the trajectory .


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

def f_store ( self , only_init = False , store_data = pypetconstants . STORE_DATA , max_depth = None ) : 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

Stores the trajectory to disk and recursively all data in the tree .


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

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 ( )

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


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)

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

Notifies the explored parameters what current point in the parameter space they should represent .


def _make_single_run(self):
        """ Modifies the trajectory for single runs executed by the environment """
        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

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


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())

def f_get_run_names ( self , sort = True ) : if sort : return [ self . f_idx_to_run ( idx ) for idx in range ( len ( self ) ) ] else : return list ( self . _run_information . keys ( ) )


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]

Returns a dictionary containing information about a single run .


def f_find_idx(self, name_list, predicate):
        """ Finds a single run index given a particular condition on parameters.

        ONLY useful for a single run if ``v_full_copy` was set to ``True``.
        Otherwise a TypeError is thrown.

        :param name_list:

            A list of parameter names the predicate applies to, if you have only a single
            parameter name you can omit the list brackets.

        :param predicate:

            A lambda predicate for filtering that evaluates to either ``True`` or  ``False``

        :return: A generator yielding the matching single run indices

        Example:

        >>> predicate = lambda param1, param2: param1==4 and param2 in [1.0, 2.0]
        >>> iterator = traj.f_find_idx(['groupA.param1', 'groupA.param2'], predicate)
        >>> [x for x in iterator]
        [0, 2, 17, 36]

        """
        if self._is_run and not self.v_full_copy:
            raise TypeError('You cannot use this function during a multiprocessing signle run and '
                            'not having ``v_full_copy=True``.')
        if isinstance(name_list, str):
            name_list = [name_list]

        # First create a list of iterators, each over the range of the matched parameters
        iter_list = []
        for name in name_list:
            param = self.f_get(name)
            if not param.v_is_parameter:
                raise TypeError('`%s` is not a parameter it is a %s, find idx is not applicable' %
                                (name, str(type(param))))

            if param.f_has_range():
                iter_list.append(iter(param.f_get_range(copy=False)))
            else:
                iter_list.append(itools.repeat(param.f_get(), len(self)))

        # Create a logical iterator returning `True` or `False`
        # whether the user's predicate matches the parameter data
        logic_iter = map(predicate, *iter_list)

        # Now the run indices are the the indices where `logic_iter` evaluates to `True`
        for idx, item in enumerate(logic_iter):
            if item:
                yield idx

Finds a single run index given a particular condition on parameters .


def f_start_run(self, run_name_or_idx=None, turn_into_run=True):
        """ Can be used to manually allow running of an experiment without using an environment.

        :param run_name_or_idx:

            Can manually set a trajectory to a particular run. If `None` the current run
            the trajectory is set to is used.

        :param turn_into_run:

            Turns the trajectory into a run, i.e. reduces functionality but makes storing
            more efficient.

        """
        if self._run_started:
            return self

        if run_name_or_idx is None:
            if self.v_idx == -1:
                raise ValueError('Cannot start run if trajectory is not set to a particular run')
        else:
            self.f_set_crun(run_name_or_idx)

        self._run_started = True

        if turn_into_run:
            self._make_single_run()

        self._set_start()

        return self

Can be used to manually allow running of an experiment without using an environment .


def f_finalize_run(self, store_meta_data=True, clean_up=True):
        """ Can be called to finish a run if manually started.

        Does NOT reset the index of the run,
        i.e. ``f_restore_default`` should be called manually if desired.

        Does NOT store any data (except meta data) so you have to call
        ``f_store`` manually before to avoid data loss.

        :param store_meta_data:

            If meta data like the runtime should be stored

        :param clean_up:

            If data added during the run should be cleaned up.
            Only works if ``turn_into_run`` was set to ``True``.

        """
        if not self._run_started:
            return self

        self._set_finish()

        if clean_up and self._is_run:
            self._finalize_run()

        self._is_run = False
        self._run_started = False

        self._updated_run_information.add(self.v_idx)

        if store_meta_data:
            self.f_store(only_init=True)

        return self

def f_finalize_run ( self , store_meta_data = True , clean_up = True ) : if not self . _run_started : return self self . _set_finish ( ) if clean_up and self . _is_run : self . _finalize_run ( ) self . _is_run = False self . _run_started = False self . _updated_run_information . add ( self . v_idx ) if store_meta_data : self . f_store ( only_init = True ) return self

Can be called to finish a run if manually started .


def _set_start(self):
        """ Sets the start timestamp and formatted time to the current time. """
        init_time = time.time()
        formatted_time = datetime.datetime.fromtimestamp(init_time).strftime('%Y_%m_%d_%Hh%Mm%Ss')
        run_info_dict = self._run_information[self.v_crun]
        run_info_dict['timestamp'] = init_time
        run_info_dict['time'] = formatted_time
        if self._environment_hexsha is not None:
            run_info_dict['short_environment_hexsha'] = self._environment_hexsha[0:7]

def _set_start ( self ) : init_time = time . time ( ) formatted_time = datetime . datetime . fromtimestamp ( init_time ) . strftime ( '%Y_%m_%d_%Hh%Mm%Ss' ) run_info_dict = self . _run_information [ self . v_crun ] run_info_dict [ 'timestamp' ] = init_time run_info_dict [ 'time' ] = formatted_time if self . _environment_hexsha is not None : run_info_dict [ 'short_environment_hexsha' ] = self . _environment_hexsha [ 0 : 7 ]

Sets the start timestamp and formatted time to the current time .


def _set_finish(self):
        """ Sets the finish time and computes the runtime in human readable format """

        run_info_dict = self._run_information[self.v_crun]
        timestamp_run = run_info_dict['timestamp']

        run_summary = self._summarize_explored_parameters()

        finish_timestamp_run = time.time()

        findatetime = datetime.datetime.fromtimestamp(finish_timestamp_run)
        startdatetime = datetime.datetime.fromtimestamp(timestamp_run)

        runtime_run = str(findatetime - startdatetime)

        run_info_dict['parameter_summary'] = run_summary
        run_info_dict['completed'] = 1
        run_info_dict['finish_timestamp'] = finish_timestamp_run
        run_info_dict['runtime'] = runtime_run

def _set_finish ( self ) : run_info_dict = self . _run_information [ self . v_crun ] timestamp_run = run_info_dict [ 'timestamp' ] run_summary = self . _summarize_explored_parameters ( ) finish_timestamp_run = time . time ( ) findatetime = datetime . datetime . fromtimestamp ( finish_timestamp_run ) startdatetime = datetime . datetime . fromtimestamp ( timestamp_run ) runtime_run = str ( findatetime - startdatetime ) run_info_dict [ 'parameter_summary' ] = run_summary run_info_dict [ 'completed' ] = 1 run_info_dict [ 'finish_timestamp' ] = finish_timestamp_run run_info_dict [ 'runtime' ] = runtime_run


def _construct_instance(self, constructor, full_name, *args, **kwargs):
        """ Creates a new node. Checks if the new node needs to know the trajectory.

        :param constructor:  The constructor to use
        :param full_name: Full name of node
        :param args: Arguments passed to constructor
        :param kwargs: Keyword arguments passed to the constructor
        :return:
        """
        if getattr(constructor, 'KNOWS_TRAJECTORY', False):
            return constructor(full_name, self, *args, **kwargs)
        else:
            return constructor(full_name, *args, **kwargs)

def _construct_instance ( self , constructor , full_name , * args , * * kwargs ) : if getattr ( constructor , 'KNOWS_TRAJECTORY' , False ) : return constructor ( full_name , self , * args , * * kwargs ) else : return constructor ( full_name , * args , * * kwargs )

Creates a new node . Checks if the new node needs to know the trajectory .


def _return_item_dictionary(param_dict, fast_access, copy):
        """Returns a dictionary containing either all parameters, all explored parameters,
        all config, all derived parameters, or all results.

        :param param_dict: The dictionary which is about to be returned
        :param fast_access: Whether to use fast access
        :param copy: If the original dict should be returned or a shallow copy

        :return: The dictionary

        :raises: ValueError if `copy=False` and fast_access=True`

        """

        if not copy and fast_access:
            raise ValueError('You cannot access the original dictionary and use fast access at the'
                             ' same time!')
        if not fast_access:
            if copy:
                return param_dict.copy()
            else:
                return param_dict
        else:
            resdict = {}
            for key in param_dict:
                param = param_dict[key]

                val = param.f_get()
                resdict[key] = val

            return resdict

Returns a dictionary containing either all parameters all explored parameters all config all derived parameters or all results .


def _finalize_run(self):
        """Called by the environment after storing to perform some rollback operations.

        All results and derived parameters created in the current run are removed.

        Important for single processing to not blow up the parent trajectory with the results
        of all runs.

        """
        self._run_information[self.v_crun]['completed'] = 1
        while len(self._new_links):
            name_pair, child_parent_pair = self._new_links.popitem(last=False)
            parent_node, _ = child_parent_pair
            _, link = name_pair
            parent_node.f_remove_child(link)

        while len(self._new_nodes):
            _, child_parent_pair = self._new_nodes.popitem(last=False)
            parent, child = child_parent_pair
            child_name = child.v_name
            parent.f_remove_child(child_name, recursive=True)

def _finalize_run ( self ) : self . _run_information [ self . v_crun ] [ 'completed' ] = 1 while len ( self . _new_links ) : name_pair , child_parent_pair = self . _new_links . popitem ( last = False ) parent_node , _ = child_parent_pair _ , link = name_pair parent_node . f_remove_child ( link ) while len ( self . _new_nodes ) : _ , child_parent_pair = self . _new_nodes . popitem ( last = False ) parent , child = child_parent_pair child_name = child . v_name parent . f_remove_child ( child_name , recursive = True )

Called by the environment after storing to perform some rollback operations .


def f_get_config(self, fast_access=False, copy=True):
        """Returns a dictionary containing the full config names as keys and the config parameters
        or the config parameter data items as values.

        :param fast_access:

            Determines whether the parameter objects or their values are returned
            in the dictionary.

        :param copy:

            Whether the original dictionary or a shallow copy is returned.
            If you want the real dictionary please do not modify it at all!
            Not Copying and fast access do not work at the same time! Raises ValueError
            if fast access is true and copy false.

        :return: Dictionary containing the config data

        :raises: ValueError

        """
        return self._return_item_dictionary(self._config, fast_access, copy)

def f_get_config ( self , fast_access = False , copy = True ) : return self . _return_item_dictionary ( self . _config , fast_access , copy )

Returns a dictionary containing the full config names as keys and the config parameters or the config parameter data items as values .


def f_get_results(self, fast_access=False, copy=True):
        """ Returns a dictionary containing the full result names as keys and the corresponding
        result objects or result data items as values.

        :param fast_access:

            Determines whether the result objects or their values are returned
            in the dictionary. Works only for results if they contain a single item with
            the name of the result.

        :param copy:

            Whether the original dictionary or a shallow copy is returned.
            If you want the real dictionary please do not modify it at all!
            Not Copying and fast access do not work at the same time! Raises ValueError
            if fast access is true and copy false.

        :return: Dictionary containing the results.

        :raises: ValueError

        """
        return self._return_item_dictionary(self._results, fast_access, copy)

def f_get_results ( self , fast_access = False , copy = True ) : return self . _return_item_dictionary ( self . _results , fast_access , copy )

Returns a dictionary containing the full result names as keys and the corresponding result objects or result data items as values .