def _ingest_experiments()

in lib/ramble/ramble/experiment_set.py [0:0]


    def _ingest_experiments(self, die_on_validate_error=True):
        """Ingest experiments based on the current context.

        Merge all contexts, and render individual experiments. Track these
        experiments within this experiment set.

        Args:
            None

        Returns:
            None
        """

        no_var_contexts = [
            self._contexts.global_conf,
            self._contexts.base,
            self._contexts.required,
        ]
        final_context = ramble.context.Context()

        for context in self._contexts:
            final_context.merge_context(self._context[context])

        for context in self._contexts:
            if context not in no_var_contexts:
                var_name = f"{context.name}_name"
                if var_name not in final_context.variables:
                    final_context.variables[var_name] = self._context[context].context_name

        # Set namespaces
        final_context.variables[self.keywords.application_namespace] = self.application_namespace
        final_context.variables[self.keywords.workload_namespace] = self.workload_namespace
        final_context.variables[self.keywords.experiment_namespace] = self.experiment_namespace

        # Set required variables for directories.
        final_context.variables[self.keywords.application_run_dir] = os.path.join(
            self._workspace.experiment_dir, Expander.expansion_str(self.keywords.application_name)
        )
        final_context.variables[self.keywords.application_input_dir] = os.path.join(
            self._workspace.input_dir, Expander.expansion_str(self.keywords.application_name)
        )

        final_context.variables[self.keywords.workload_run_dir] = os.path.join(
            Expander.expansion_str(self.keywords.application_run_dir),
            Expander.expansion_str(self.keywords.workload_name),
        )
        final_context.variables[self.keywords.workload_input_dir] = os.path.join(
            Expander.expansion_str(self.keywords.application_input_dir),
            Expander.expansion_str(self.keywords.workload_name),
        )

        final_context.variables[self.keywords.license_input_dir] = os.path.join(
            self._workspace.shared_license_dir,
            Expander.expansion_str(self.keywords.application_name),
        )

        final_context.variables[self.keywords.experiment_run_dir] = os.path.join(
            Expander.expansion_str(self.keywords.workload_run_dir),
            Expander.expansion_str(self.keywords.experiment_name),
        )

        experiment_template_name = final_context.variables[self.keywords.experiment_name]

        renderer = ramble.renderer.Renderer()

        render_group = ramble.renderer.RenderGroup("experiment", "create")
        render_group.variables = final_context.variables
        render_group.zips = final_context.zips
        render_group.matrices = final_context.matrices
        render_group.n_repeats = final_context.n_repeats
        render_group.used_variables = set()

        excluded_experiments = set()
        if final_context.exclude:
            exclude_group = ramble.renderer.RenderGroup("experiment", "exclude")
            exclude_group.copy_contents(render_group)
            perform_explicit_exclude = exclude_group.from_dict(
                experiment_template_name, final_context.exclude
            )

            if perform_explicit_exclude:
                for exclude_exp_vars, _ in renderer.render_objects(
                    exclude_group, ignore_used=False
                ):
                    expander = ramble.expander.Expander(exclude_exp_vars, self)
                    self._compute_mpi_vars(expander, exclude_exp_vars)
                    exclude_exp_name = expander.expand_var(
                        experiment_template_name, allow_passthrough=False
                    )
                    excluded_experiments.add(exclude_exp_name)

        exclude_where = []
        if final_context.exclude:
            if namespace.where in final_context.exclude:
                exclude_where = final_context.exclude[namespace.where]

        tracking_group = ramble.renderer.RenderGroup("experiment", "create")
        tracking_group.variables = final_context.variables
        tracking_group.zips = final_context.zips
        tracking_group.matrices = final_context.matrices
        tracking_group.n_repeats = final_context.n_repeats
        tracking_group.used_variables = set()

        used_variables = set()
        for tracking_vars, repeats in renderer.render_objects(
            tracking_group, exclude_where=exclude_where, ignore_used=False, fatal=False
        ):
            app_inst = self._prepare_experiment(
                experiment_template_name,
                tracking_vars,
                final_context,
                repeats,
            )

            exp_used_variables = app_inst.build_used_variables(self._workspace)
            used_variables = used_variables.union(exp_used_variables)
        render_group.used_variables = used_variables.copy()

        rendered_experiments = set()
        for experiment_vars, repeats in renderer.render_objects(
            render_group, exclude_where=exclude_where
        ):
            app_inst = self._prepare_experiment(
                experiment_template_name,
                experiment_vars,
                final_context,
                repeats,
            )

            final_exp_name = app_inst.expander.expand_var_name(self.keywords.experiment_name)
            final_exp_namespace = app_inst.expander.expand_var_name(
                self.keywords.experiment_namespace
            )

            # Skip explicitly excluded experiments
            if final_exp_name not in excluded_experiments:
                logger.debug(f"   Final name: {final_exp_namespace}")

                if final_exp_namespace in rendered_experiments:
                    left_vars = self.experiments[final_exp_namespace].variables
                    right_vars = experiment_vars
                    lkeys = set(left_vars.keys())
                    rkeys = set(right_vars.keys())

                    # Determine variables that are only in one of the two experiments
                    left_unique_vars = lkeys - rkeys
                    right_unique_vars = rkeys - lkeys
                    common_vars = lkeys & rkeys

                    logger.warn(f"Two experiments are defined with the name {final_exp_namespace}")

                    # Print warnings about experiment differences
                    if left_unique_vars:
                        logger.warn("Variables unique to previously defined experiment:")
                        for var in left_unique_vars:
                            logger.warn(f"  - {var}")

                    if right_unique_vars:
                        logger.warn("Variables unique to newly defined experiment:")
                        for var in right_unique_vars:
                            logger.warn(f"  - {var}")

                    print_header = True
                    for var in common_vars:
                        if left_vars[var] != right_vars[var]:
                            if print_header:
                                logger.warn("Variable differences between experiment definitions:")
                                print_header = False

                            diff = {"previous": left_vars[var], "new": right_vars[var]}
                            logger.warn(f"  - {var}: {diff}")

                    logger.die(f"Experiment {final_exp_namespace} is not unique.")

                try:
                    app_inst.validate_experiment(
                        warn_validation=True, die_on_validate_error=die_on_validate_error
                    )
                except ramble.keywords.RambleKeywordError as e:
                    if die_on_validate_error:
                        raise RambleVariableDefinitionError(
                            f"In experiment {final_exp_namespace}: {e}"
                        )
                    pass

                rendered_experiments.add(final_exp_namespace)
                self.experiments[final_exp_namespace] = app_inst
                self.experiment_order.append(final_exp_namespace)