def _initialize_components(self,
                               experiment_data: ExperimentData) -> List[str]:
        """Initialize child data components and return list of child experiment IDs"""
        # Check if component child experiment data containers have already
        # been created. If so the list of indices for their positions in the
        # ordered dict should exist. Index is used to extract the experiment
        # IDs for each child experiment which can change when re-running analysis
        # if replace_results=False, so that we update the correct child data
        # for each component experiment
        component_index = experiment_data.metadata.get("component_child_index",
                                                       [])
        if not component_index:
            experiment = experiment_data.experiment
            if experiment is None:
                raise AnalysisError(
                    "Cannot run composite analysis on an experiment data without either "
                    "a composite experiment, or composite experiment metadata."
                )
            # If the experiment Construct component data and update indices
            start_index = len(experiment_data.child_data())
            component_index = []
            for i, sub_exp in enumerate(experiment.component_experiment()):
                sub_data = sub_exp._initialize_experiment_data()
                experiment_data.add_child_data(sub_data)
                component_index.append(start_index + i)
            experiment_data.metadata["component_child_index"] = component_index

        # Child components exist so we can get their ID for accessing them
        child_ids = experiment_data._child_data.keys()
        component_ids = [child_ids[idx] for idx in component_index]
        return component_ids
    def _add_child_data(self, experiment_data: ExperimentData):
        """Save empty component experiment data as child data.

        This will initialize empty ExperimentData objects for each component
        experiment and add them as child data to the main composite experiment
        ExperimentData container container for saving.

        Args:
            experiment_data: a composite experiment experiment data container.
        """
        component_index = experiment_data.metadata.get("component_child_index",
                                                       [])
        if component_index:
            # Child components are already initialized
            return

        # Initialize the component experiment data containers and add them
        # as child data to the current experiment data
        child_components = self._initialize_component_experiment_data(
            experiment_data)
        start_index = len(experiment_data.child_data())
        for i, subdata in enumerate(child_components):
            experiment_data.add_child_data(subdata)
            component_index.append(start_index + i)

        # Store the indices of the added child data in metadata
        experiment_data.metadata["component_child_index"] = component_index
 def _initialize_experiment_data(self):
     """Initialize the return data container for the experiment run"""
     experiment_data = ExperimentData(experiment=self)
     # Initialize child experiment data
     for sub_exp in self._experiments:
         sub_data = sub_exp._initialize_experiment_data()
         experiment_data.add_child_data(sub_data)
     experiment_data.metadata["component_child_index"] = list(range(self.num_experiments))
     return experiment_data