'Returns a subset of the current dag as a deep copy of the current dag
based on a regex that should match one or many tasks, and includes
upstream and downstream neighbours based on the flag passed.'

def sub_dag(self, task_regex, include_downstream=False, include_upstream=True):

    dag = copy.deepcopy(self)
    regex_match = [t for t in dag.tasks if re.findall(task_regex, t.task_id)]
    also_include = []
    for t in regex_match:
        if include_downstream:
            also_include += t.get_flat_relatives(upstream=False)
        if include_upstream:
            also_include += t.get_flat_relatives(upstream=True)
    dag.task_dict = {t.task_id: t for t in (regex_match + also_include)}
    for t in dag.tasks:
        t._upstream_task_ids = [tid for tid in t._upstream_task_ids if (tid in dag.task_ids)]
        t._downstream_task_ids = [tid for tid in t._downstream_task_ids if (tid in dag.task_ids)]
    if (len(dag.tasks) < len(self.tasks)):
        dag.partial = True
    return dag
