def _fan_out(self, node, options):
        # get all edges of the node and
        # a list of list of values on which we fanout the
        # node
        _edges = list(node._edges)
        values = [o.expand() for o in options]
        log.info("Fanout | %s with %d options %d values",
                 node, len(options), len(values[0]))

        incoming_links = []
        incoming_edges = []
        incoming_links_set = set([])
        # collect incoming edges to the fan node that are covered
        # by fan_options. We will not add them explicitly but
        # one for each new clone
        for e in _edges:
            if e._target == node:
                for link in e._links:
                    if link[1] in options and not link in incoming_links_set:
                        incoming_links.append(link)
                        incoming_edges.append(e)
                        incoming_links_set.add(link)
        log.debug("Fanout | incoming edges: %s", incoming_edges)
        log.debug("Fanout | incoming values: %s", values)

        need_to_clone_edges = [e for e in _edges if not e in incoming_edges]

        # clone the tool
        for i, opts in enumerate(zip(*values)):
            log.debug("Fanout | Clone node: %s", node)
            cloned_tool = node._tool.clone()
            # Add the cloned tool to the current graph
            cloned_node = self.add(cloned_tool, _job=node._job)
            cloned_node._pipeline = node._pipeline
            log.debug("Fanout | Added new node: %s", cloned_node)
            # reattach all edge that are not part of the fanout
            # and copy the links. We will resolve the incoming edges
            # in the next step
            for edge in need_to_clone_edges:
                self._fanout_add_edge(edge, node, cloned_node)

            # now apply the options and create the incoming edges
            for j, option in enumerate(options):
                if i < len(incoming_edges):
                    e = incoming_edges[i]
                    new_edge = self.add_edge(e._source, cloned_node)
                    new_edge._group = e._group
                    for link in e._links:
                        link = new_edge.add_link(
                            link[0],
                            cloned_tool.options[link[1].name]
                        )
                        log.debug("Fanout | add link from inedge to edge: "
                                  "%s [%s]", link, new_edge)
                # get the new value
                o = opts[j]
                allow_stream = False
                cloned_node.set(option.name, o, set_dep=False,
                                allow_stream=allow_stream)
                #cloned_node._tool.options[option.name]._index = i
                ost = str(o) if not isinstance(o, Option) else o._value
                log.debug("Fanout | apply value %s: %s=%s", cloned_node,
                          option.name, ost)
                ooo = cloned_node._tool.options[option.name]
                ooo.dependency = option.dependency
                ooo._index = i

        #node._tool.setup()
        _create_render_context(self, node._tool, node, None)
        self.remove(node)
Fan-out the given node using the given options
dataset/ETHPy150Open thasso/pyjip/jip/pipelines.py/Pipeline._fan_out