Save the experiment configuration

        This method stores the configuration of each of the experiments in a
        file ``'<project-dir>/.project/<experiment>.yml'``, where
        ``'<project-dir>'`` corresponds to the project directory of the
        specific ``'<experiment>'``. Furthermore it dumps all experiments to
        the :attr:`exp_file` configuration file.

def save(self):
        """Save the experiment configuration

        This method stores the configuration of each of the experiments in a
        file ``'<project-dir>/.project/<experiment>.yml'``, where
        ``'<project-dir>'`` corresponds to the project directory of the
        specific ``'<experiment>'``. Furthermore it dumps all experiments to
        the :attr:`exp_file` configuration file.
        """
        for exp, d in dict(self).items():
            if isinstance(d, dict):
                project_path = self.projects[d['project']]['root']
                d = self.rel_paths(copy.deepcopy(d))
                fname = osp.join(project_path, '.project', exp + '.yml')
                if not osp.exists(osp.dirname(fname)):
                    os.makedirs(osp.dirname(fname))
                safe_dump(d, fname, default_flow_style=False)
        exp_file = self.exp_file
        # to be 100% sure we do not write to the file from multiple processes
        lock = fasteners.InterProcessLock(exp_file + '.lck')
        lock.acquire()
        safe_dump(OrderedDict((exp, val if isinstance(val, Archive) else None)
                              for exp, val in self.items()),
                  exp_file, default_flow_style=False)
        lock.release()