def METHOD_NAME(clusters, profiler=None, **kwargs):
    """
    Create a ScheduleTree from a ClusterGroup.
    """
    clusters = preprocess(clusters, **kwargs)
    stree = ScheduleTree()
    section = None
    prev = Cluster(None)
    mapper = DefaultOrderedDict(lambda: Bunch(top=None, middle=None, bottom=None))
    mapper[base] = Bunch(top=stree, middle=stree, bottom=stree)
    for c in clusters:
        if reuse_whole_subtree(c, prev):
            tip = mapper[base].bottom
            maybe_reusable = prev.itintervals
        else:
            # Add any guards/Syncs outside of the outermost Iteration
            tip = augment_whole_subtree(c, stree, mapper, base)
            maybe_reusable = []
        index = 0
        for it0, it1 in zip(c.itintervals, maybe_reusable):
            if it0 != it1:
                break
            d = it0.dim
            if needs_nodehalo(d, c.halo_scheme):
                break
            index += 1
            # The reused sub-trees might acquire new sub-iterators as well as
            # new properties
            mapper[it0].top.ispace = IterationSpace.union(
                mapper[it0].top.ispace, c.ispace.project([d])
            )
            mapper[it0].top.properties = normalize_properties(
                mapper[it0].top.properties, c.properties[it0.dim]
            )
            if reuse_whole_subtree(c, prev, d):
                tip = mapper[it0].bottom
            elif reuse_partial_subtree(c, prev, d):
                tip = mapper[it0].middle
                tip = augment_partial_subtree(c, tip, mapper, it0)
                break
            else:
                tip = mapper[it0].top
                tip = augment_whole_subtree(c, tip, mapper, it0)
                break
        # Nested sub-trees, instead, will not be used anymore
        for it in prev.itintervals[index:]:
            mapper.pop(it)
        prev = c
        # Add in Node{Iteration,Conditional,Sync}
        for it in c.itintervals[index:]:
            d = it.dim
            tip = NodeIteration(c.ispace.project([d]), tip, c.properties.get(d, ()))
            mapper[it].top = tip
            tip = augment_whole_subtree(c, tip, mapper, it)
        # Attach NodeHalo if necessary
        for it, v in mapper.items():
            if needs_nodehalo(it.dim, c.halo_scheme):
                v.bottom.parent = NodeHalo(c.halo_scheme, v.bottom.parent)
                break
        # Add in NodeExprs
        exprs = []
        for conditionals, g in groupby(c.exprs, key=lambda e: e.conditionals):
            exprs = list(g)
            # Indirect ConditionalDimensions induce expression-level guards
            if conditionals:
                guard = And(*conditionals.values(), evaluate=False)
                parent = NodeConditional(guard, tip)
            else:
                parent = tip
            NodeExprs(exprs, c.ispace, c.dspace, c.ops, c.traffic, parent)
        # Nest within a NodeSection if possible
        if profiler is None or \
           any(i.is_Section for i in reversed(tip.ancestors)):
            continue
        candidate = None
        for i in reversed(tip.ancestors + (tip,)):
            if i.is_Halo:
                candidate = i
            elif i.is_Sync:
                attach_section(i)
                section = None
                break
            elif i.is_Iteration:
                if (i.dim.is_Time and SEQUENTIAL in i.properties):
                    section = attach_section(candidate, section)
                    break
                else:
                    candidate = i
        else:
            attach_section(candidate, section)
    return stree