def run(self, *pipelines, **kwargs):
        """
        Connects all pipelines to that study's repository and runs them
        in the same NiPype workflow

        Parameters
        ----------
        pipeline(s) : Pipeline, ...
            The pipeline to connect to repository
        required_outputs : list[set[str]]
            A set of required outputs for each pipeline. If None then all
            outputs are assumed to be required
        subject_ids : list[str]
            The subset of subject IDs to process. If None all available will be
            processed. Note this is not a duplication of the study
            and visit IDs passed to the Study __init__, as they define the
            scope of the analysis and these simply limit the scope of the
            current run (e.g. to break the analysis into smaller chunks and
            run separately). Therefore, if the analysis joins over subjects,
            then all subjects will be processed and this parameter will be
            ignored.
        visit_ids : list[str]
            The same as 'subject_ids' but for visit IDs
        session_ids : list[str,str]
            The same as 'subject_ids' and 'visit_ids', except specifies a set
            of specific combinations in tuples of (subject ID, visit ID).
        force : bool | 'all'
            A flag to force the reprocessing of all sessions in the filter
            array, regardless of whether the parameters|pipeline used
            to generate them matches the current ones. NB: if True only the
            final pipeline will be reprocessed (prerequisite pipelines won't
            run unless they don't match provenance). To process all
            prerequisite pipelines 'all' should be passed to force.

        Returns
        -------
        report : ReportNode
            The final report node, which can be connected to subsequent
            pipelines
        """
        if not pipelines:
            raise ArcanaUsageError("No pipelines provided to {}.run"
                                   .format(self))
        # Get filter kwargs  (NB: in Python 3 they could be in the kwarg list)
        subject_ids = kwargs.pop('subject_ids', None)
        visit_ids = kwargs.pop('visit_ids', None)
        session_ids = kwargs.pop('session_ids', None)
        clean_work_dir = kwargs.pop('clean_work_dir',
                                    self._clean_work_dir_between_runs)
        required_outputs = kwargs.pop('required_outputs', repeat(None))
        # Create name by combining pipelines
        name = '_'.join(p.name for p in pipelines)
        # Clean work dir if required
        if clean_work_dir:
            workflow_work_dir = op.join(self.work_dir, name)
            if op.exists(workflow_work_dir):
                shutil.rmtree(workflow_work_dir)
        # Trim the end of very large names to avoid problems with
        # workflow names exceeding system limits.
        name = name[:WORKFLOW_MAX_NAME_LEN]
        workflow = pe.Workflow(name=name, base_dir=self.work_dir)

        # Generate filter array to optionally restrict the run to certain
        # subject and visit IDs.
        tree = self.study.tree
        # Create maps from the subject|visit IDs to an index used to represent
        # them in the filter array
        subject_inds = {s.id: i for i, s in enumerate(tree.subjects)}
        visit_inds = {v.id: i for i, v in enumerate(tree.visits)}
        if not subject_ids and not visit_ids and not session_ids:
            # No filters applied so create a full filter array
            filter_array = np.ones((len(subject_inds), len(visit_inds)),
                                   dtype=bool)
        else:
            # Filters applied so create an empty filter array and populate
            # from filter lists
            filter_array = np.zeros((len(subject_inds), len(visit_inds)),
                                    dtype=bool)
            if subject_ids is not None:
                for subj_id in subject_ids:
                    filter_array[subject_inds[subj_id], :] = True
            if visit_ids is not None:
                for visit_id in visit_ids:
                    filter_array[:, visit_inds[visit_id]] = True
            if session_ids is not None:
                for subj_id, visit_id in session_ids:
                    filter_array[subject_inds[subj_id],
                                 visit_inds[visit_id]] = True
            if not filter_array.any():
                raise ArcanaUsageError(
                    "Provided filters:\n" +
                    ("  subject_ids: {}\n".format(', '.join(subject_ids))
                     if subject_ids is not None else '') +
                    ("  visit_ids: {}\n".format(', '.join(visit_ids))
                     if visit_ids is not None else '') +
                    ("  session_ids: {}\n".format(', '.join(session_ids))
                     if session_ids is not None else '') +
                    "Did not match any sessions in the project:\n" +
                    "  subject_ids: {}\n".format(', '.join(subject_inds)) +
                    "  visit_ids: {}\n".format(', '.join(visit_inds)))

        # Stack of pipelines to process in reverse order of required execution
        stack = OrderedDict()

        def push_on_stack(pipeline, filt_array, req_outputs):
            if req_outputs is None:
                req_outputs = pipeline.output_names
            if pipeline.name in stack:
                # Pop pipeline from stack in order to add it to the end of the
                # stack and ensure it is run before all downstream pipelines
                prev_pipeline, prev_req_outputs, prev_filt_array = stack.pop(
                    pipeline.name)
                if pipeline is not prev_pipeline and pipeline != prev_pipeline:
                    raise ArcanaDesignError(
                        "Attempting to run two different pipelines with the "
                        "same name, {} and {}".format(pipeline, prev_pipeline))
                # Combined required outputs and filter array with previous
                # references to the pipeline
                req_outputs = copy(req_outputs)
                req_outputs.update(prev_req_outputs)
                filt_array = filt_array | prev_filt_array
            # If the pipeline to process contains summary outputs (i.e. 'per-
            # subject|visit|study' frequency), then we need to "dialate" the
            # filter array to include IDs across the scope of the study, e.g.
            # all subjects for per-vist, or all visits for per-subject.
            output_freqs = set(pipeline.output_frequencies)
            dialated_filt_array = self._dialate_array(filt_array,
                                                      pipeline.joins)
            added = dialated_filt_array ^ filt_array
            if added.any():
                filt_array = dialated_filt_array
                # Invert the index dictionaries to get index-to-ID maps
                inv_subject_inds = {v: k for k, v in subject_inds.items()}
                inv_visit_inds = {v: k for k, v in visit_inds.items()}
                logger.warning(
                    "Dialated filter array used to process '{}' pipeline to "
                    "include {} subject/visit IDs due to its '{}' summary "
                    "outputs ".format(
                        pipeline.name,
                        ', '.join('({},{})'.format(inv_subject_inds[s],
                                                   inv_visit_inds[v])
                                  for s, v in zip(*np.nonzero(added))),
                        "' and '".join(output_freqs)))

            stack[pipeline.name] = pipeline, req_outputs, filt_array
            # Recursively add all prerequisites to stack
            for prq_getter, prq_req_outputs in pipeline.prerequisites.items():
                try:
                    prereq = pipeline.study.pipeline(
                        prq_getter, prq_req_outputs)
                    push_on_stack(prereq, filt_array, prq_req_outputs)
                except (ArcanaMissingDataException,
                        ArcanaOutputNotProducedException) as e:
                    e.msg += ("{}, which are required as inputs to the '{}' "
                              "pipeline to produce '{}'".format(
                                  pipeline.name, "', '".join(req_outputs)))
                    raise e

        # Add all primary pipelines to the stack along with their prereqs
        for pipeline, req_outputs in zip(pipelines, required_outputs):
            push_on_stack(pipeline, filter_array, req_outputs)

        # Iterate through stack of required pipelines from upstream to
        # downstream
        for pipeline, req_outputs, flt_array in reversed(list(stack.values())):
            try:
                self._connect_pipeline(
                    pipeline, req_outputs, workflow, subject_inds, visit_inds,
                    flt_array, **kwargs)
            except ArcanaNoRunRequiredException:
                logger.info("Not running '{}' pipeline as its outputs "
                            "are already present in the repository"
                            .format(pipeline.name))
        # Save complete graph for debugging purposes
#         workflow.write_graph(graph2use='flat', format='svg')
#         print('Graph saved in {} directory'.format(os.getcwd()))
        # Actually run the generated workflow
        result = workflow.run(plugin=self._plugin)
        # Reset the cached tree of filesets in the repository as it will
        # change after the pipeline has run.
        self.study.clear_caches()
        return result