@parse_config
    @kwargs_api_change('delete_continue', 'delete_resume')
    @kwargs_api_change('continue_folder', 'resume_folder')
    @kwargs_api_change('continuable', 'resumable')
    @kwargs_api_change('freeze_pool_input', 'freeze_input')
    @kwargs_api_change('use_hdf5', 'storage_service')
    @kwargs_api_change('dynamically_imported_classes', 'dynamic_imports')
    @kwargs_api_change('pandas_append')
    @simple_logging_config
    def __init__(self, trajectory='trajectory',
                 add_time=False,
                 comment='',
                 dynamic_imports=None,
                 wildcard_functions=None,
                 automatic_storing=True,
                 log_config=pypetconstants.DEFAULT_LOGGING,
                 log_stdout=False,
                 report_progress = (5, 'pypet', logging.INFO),
                 multiproc=False,
                 ncores=1,
                 use_scoop=False,
                 use_pool=False,
                 freeze_input=False,
                 timeout=None,
                 cpu_cap=100.0,
                 memory_cap=100.0,
                 swap_cap=100.0,
                 niceness=None,
                 wrap_mode=pypetconstants.WRAP_MODE_LOCK,
                 queue_maxsize=-1,
                 port=None,
                 gc_interval=None,
                 clean_up_runs=True,
                 immediate_postproc=False,
                 resumable=False,
                 resume_folder=None,
                 delete_resume=True,
                 storage_service=HDF5StorageService,
                 git_repository=None,
                 git_message='',
                 git_fail=False,
                 sumatra_project=None,
                 sumatra_reason='',
                 sumatra_label=None,
                 do_single_runs=True,
                 graceful_exit=False,
                 lazy_debug=False,
                 **kwargs):

        if git_repository is not None and git is None:
            raise ValueError('You cannot specify a git repository without having '
                             'GitPython. Please install the GitPython package to use '
                             'pypet`s git integration.')

        if resumable and dill is None:
            raise ValueError('Please install `dill` if you want to use the feature to '
                             'resume halted trajectories')

        if load_project is None and sumatra_project is not None:
            raise ValueError('`sumatra` package has not been found, either install '
                             '`sumatra` or set `sumatra_project=None`.')

        if sumatra_label is not None and '.' in sumatra_label:
            raise ValueError('Your sumatra label is not allowed to contain dots.')

        if wrap_mode == pypetconstants.WRAP_MODE_NETLOCK and zmq is None:
            raise ValueError('You need to install `zmq` for `NETLOCK` wrapping.')

        if (use_pool or use_scoop) and immediate_postproc:
            raise ValueError('You CANNOT perform immediate post-processing if you DO '
                             'use a pool or scoop.')

        if use_pool and use_scoop:
            raise ValueError('You can either `use_pool` or `use_scoop` or none of both, '
                             'but not both together')

        if use_scoop and scoop is None:
            raise ValueError('Cannot use `scoop` because it is not installed.')

        if (wrap_mode not in (pypetconstants.WRAP_MODE_NONE,
                              pypetconstants.WRAP_MODE_LOCAL,
                              pypetconstants.WRAP_MODE_LOCK,
                              pypetconstants.WRAP_MODE_NETLOCK) and
                                resumable):
            raise ValueError('Continuing trajectories does only work with '
                             '`LOCK`, `NETLOCK` or `LOCAL`wrap mode.')

        if resumable and not automatic_storing:
            raise ValueError('Continuing only works with `automatic_storing=True`')

        if use_scoop and wrap_mode not in (pypetconstants.WRAP_MODE_LOCAL,
                                           pypetconstants.WRAP_MODE_NONE,
                                           pypetconstants.WRAP_MODE_NETLOCK,
                                           pypetconstants.WRAP_MODE_NETQUEUE):
            raise ValueError('SCOOP mode only works with `LOCAL`, `NETLOCK` or '
                             '`NETQUEUE` wrap mode!')

        if niceness is not None and not hasattr(os, 'nice') and psutil is None:
            raise ValueError('You cannot set `niceness` if your operating system does not '
                             'support the `nice` operation. Alternatively you can install '
                             '`psutil`.')

        if freeze_input and not use_pool and not use_scoop:
            raise ValueError('You can only use `freeze_input=True` if you either use '
                             'a pool or SCOOP.')

        if not isinstance(memory_cap, tuple):
            memory_cap = (memory_cap, 0.0)

        if (cpu_cap <= 0.0 or cpu_cap > 100.0 or
            memory_cap[0] <= 0.0 or memory_cap[0] > 100.0 or
                swap_cap <= 0.0 or swap_cap > 100.0):
            raise ValueError('Please choose cap values larger than 0.0 '
                             'and smaller or equal to 100.0.')

        check_usage = cpu_cap < 100.0 or memory_cap[0] < 100.0 or swap_cap < 100.0

        if check_usage and psutil is None:
            raise ValueError('You cannot enable monitoring without having '
                             'installed psutil. Please install psutil or set '
                             'cpu_cap, memory_cap, and swap_cap to 100.0')

        if ncores == 0 and psutil is None:
            raise ValueError('You cannot set `ncores=0` for auto detection of CPUs if you did not '
                             'installed psutil. Please install psutil or '
                             'set `ncores` manually.')

        if port is not None and wrap_mode not in (pypetconstants.WRAP_MODE_NETLOCK,
                                                  pypetconstants.WRAP_MODE_NETQUEUE):
            raise ValueError('You can only specify a port for the `NETLOCK` wrapping.')

        if use_scoop and graceful_exit:
            raise ValueError('You cannot exit gracefully using SCOOP.')

        unused_kwargs = set(kwargs.keys())

        self._logging_manager = LoggingManager(log_config=log_config,
                                               log_stdout=log_stdout,
                                               report_progress=report_progress)
        self._logging_manager.check_log_config()
        self._logging_manager.add_null_handler()
        self._set_logger()

        self._map_arguments = False
        self._stop_iteration = False  # Marker to cancel
        # iteration in case of Keyboard interrupt
        self._graceful_exit = graceful_exit

        # Helper attributes defined later on
        self._start_timestamp = None
        self._finish_timestamp = None
        self._runtime = None

        self._cpu_cap = cpu_cap
        self._memory_cap = memory_cap
        if psutil is not None:
            # Total memory in MB
            self._total_memory = psutil.virtual_memory().total / 1024.0 / 1024.0
            # Estimated memory needed by each process as ratio
            self._est_per_process = self._memory_cap[1] / self._total_memory * 100.0
        self._swap_cap = swap_cap
        self._check_usage = check_usage
        self._last_cpu_check = 0.0
        self._last_cpu_usage = 0.0
        if self._check_usage:
            # For initialisation
            self._estimate_cpu_utilization()
        self._niceness = niceness

        self._sumatra_project = sumatra_project
        self._sumatra_reason = sumatra_reason
        self._sumatra_label = sumatra_label
        self._loaded_sumatatra_project = None
        self._sumatra_record = None

        self._runfunc = None
        self._args = ()
        self._kwargs = {}

        self._postproc = None
        self._postproc_args = ()
        self._postproc_kwargs = {}
        self._immediate_postproc = immediate_postproc
        self._user_pipeline = False

        self._git_repository = git_repository
        self._git_message = git_message
        self._git_fail = git_fail

        # Check if a novel trajectory needs to be created.
        if isinstance(trajectory, compat.base_type):
            # Create a new trajectory
            self._traj = Trajectory(trajectory,
                                    add_time=add_time,
                                    dynamic_imports=dynamic_imports,
                                    wildcard_functions=wildcard_functions,
                                    comment=comment)

            self._timestamp = self.trajectory.v_timestamp  # Timestamp of creation
            self._time = self.trajectory.v_time  # Formatted timestamp
        else:
            self._traj = trajectory
            # If no new trajectory is created the time of the environment differs
            # from the trajectory and must be computed from the current time.
            init_time = time.time()
            formatted_time = format_time(init_time)
            self._timestamp = init_time
            self._time = formatted_time

        # In case the user provided a git repository path, a git commit is performed
        # and the environment's hexsha is taken from the commit if the commit was triggered by
        # this particular environment, otherwise a new one is generated
        if self._git_repository is not None:
            new_commit, self._hexsha = make_git_commit(self, self._git_repository,
                                                       self._git_message, self._git_fail)
            # Identifier hexsha
        else:
            new_commit = False

        if not new_commit:
            # Otherwise we need to create a novel hexsha
            self._hexsha = hashlib.sha1(compat.tobytes(self.trajectory.v_name +
                                                       str(self.trajectory.v_timestamp) +
                                                       str(self.timestamp) +
                                                           VERSION)).hexdigest()

        # Create the name of the environment
        short_hexsha = self._hexsha[0:7]
        name = 'environment'
        self._name = name + '_' + str(short_hexsha) + '_' + self._time  # Name of environment

        # The trajectory should know the hexsha of the current environment.
        # Thus, for all runs, one can identify by which environment they were run.
        self._traj._environment_hexsha = self._hexsha
        self._traj._environment_name = self._name

        self._logging_manager.extract_replacements(self._traj)
        self._logging_manager.remove_null_handler()
        self._logging_manager.make_logging_handlers_and_tools()

        # Drop a message if we made a commit. We cannot drop the message directly after the
        # commit, because the logging files do not exist yet,
        # and we want this commit to be tracked
        if self._git_repository is not None:
            if new_commit:
                self._logger.info('Triggered NEW GIT commit `%s`.' % str(self._hexsha))
            else:
                self._logger.info('No changes detected, added PREVIOUS GIT commit `%s`.' %
                                  str(self._hexsha))

        # Create the storage service
        if storage_service is True: # to allow compatibility with older python versions, i.e. old
            # keyword use_hdf5
            storage_service = HDF5StorageService
        if self._traj.v_storage_service is not None:
            # Use the service of the trajectory
            self._logger.info('Found storage service attached to Trajectory. Will use '
                              'this storage service.')
            self._storage_service = self.trajectory.v_storage_service
        else:
            # Create a new service
            self._storage_service, unused_factory_kwargs = storage_factory(storage_service,
                                                                        self._traj, **kwargs)
            unused_kwargs = unused_kwargs - (set(kwargs.keys()) - unused_factory_kwargs)

        if lazy_debug and is_debug():
            self._storage_service = LazyStorageService()

        self._traj.v_storage_service = self._storage_service

        # Create resume path if desired
        self._resumable = resumable

        if self._resumable:
            if resume_folder is None:
                resume_folder = os.path.join(os.getcwd(), 'resume')
            resume_path = os.path.join(resume_folder, self._traj.v_name)
        else:
            resume_path = None

        self._resume_folder = resume_folder
        self._resume_path = resume_path
        self._delete_resume = delete_resume

        # Check multiproc
        self._multiproc = multiproc
        if ncores == 0:
            # Let *pypet* detect CPU count via psutil
            ncores = psutil.cpu_count()
            self._logger.info('Determined CPUs automatically, found `%d` cores.' % ncores)
        self._ncores = ncores
        if queue_maxsize == -1:
            # Educated guess of queue size
            queue_maxsize = 2 * ncores
        self._queue_maxsize = queue_maxsize
        if wrap_mode is None:
            # None cannot be used in HDF5 files, accordingly we need a string representation
            wrap_mode = pypetconstants.WRAP_MODE_NONE
        self._wrap_mode = wrap_mode
        # Whether to use a pool of processes
        self._use_pool = use_pool
        self._use_scoop = use_scoop
        self._freeze_input = freeze_input
        self._gc_interval = gc_interval
        self._multiproc_wrapper = None # The wrapper Service

        self._do_single_runs = do_single_runs
        self._automatic_storing = automatic_storing
        self._clean_up_runs = clean_up_runs

        if (wrap_mode == pypetconstants.WRAP_MODE_NETLOCK and
                not isinstance(port, compat.base_type)):
                url = port_to_tcp(port)
                self._logger.info('Determined lock-server URL automatically, it is `%s`.' % url)
        else:
            url = port
        self._url = url
        self._timeout = timeout
        # self._deep_copy_data = False  # deep_copy_data # For future reference deep_copy_arguments

        # Notify that in case of lazy debuggin we won't record anythin
        if lazy_debug and is_debug():
            self._logger.warning('Using the LazyStorageService, nothing will be saved to disk.')

        # Current run index to avoid quadratic runtime complexity in case of re-running
        self._current_idx = 0

        self._trajectory_name = self._traj.v_name
        for kwarg in list(unused_kwargs):
            try:
                val = kwargs[kwarg]
                self._traj.f_set_properties(**{kwarg: val})
                self._logger.info('Set trajectory property `%s` to `%s`.' % (kwarg, str(val)))
                unused_kwargs.remove(kwarg)
            except __HOLE__:
                pass
        if len(unused_kwargs) > 0:
            raise ValueError('You passed keyword arguments to the environment that you '
                                 'did not use. The following keyword arguments were ignored: '
                                 '`%s`' % str(unused_kwargs))

        # Add all config data to the environment
        self._add_config()

        self._logger.info('Environment initialized.')
dataset/ETHPy150Open SmokinCaterpillar/pypet/pypet/environment.py/Environment.__init__