Build a graphviz schema of a reliure :class:`.Engine`.
    
    It depends on `graphviz <https://pypi.python.org/pypi/graphviz>`_.

    :param engine: reliure engine to graph
    :type engine: :class:`.Engine`
    :param out_names: list of block output to consider as engine output (all by default)
    :param filename: output filename, create the file if given
    :param formal: output file formal (pdf, svg, png, ...)

    >>> from reliure.engine import Engine
    >>> egn = Engine("preproc", "proc1", "proc2")
    >>> egn.preproc.setup(in_name="input", out_name="data")
    >>> egn.proc1.setup(in_name="data", out_name="gold_data")
    >>> egn.proc2.setup(in_name="input", out_name="silver_data")
    >>> # you can create
    >>> schema = engine_schema(egn, filename='docs/img/engine_schema', format='png')

    it create the following image :

    .. image:: /../_static/engine_schema.png

    You can specify which block output will be consider as engine output:

    >>> schema = engine_schema(egn, ["gold_data", "silver_data"], filename='docs/img/engine_schema_simple', format='png')

    .. image:: /../_static/engine_schema_simple.png

    Note that it is also possible to draw a pdf;

    >>> schema = engine_schema(egn, ["gold_data", "silver_data"], filename='docs/img/engine_schema_simple', format='pdf')

def engine_schema(engine, out_names=None, filename=None, format="pdf"):
    """ Build a graphviz schema of a reliure :class:`.Engine`.
    
    It depends on `graphviz <https://pypi.python.org/pypi/graphviz>`_.

    :param engine: reliure engine to graph
    :type engine: :class:`.Engine`
    :param out_names: list of block output to consider as engine output (all by default)
    :param filename: output filename, create the file if given
    :param formal: output file formal (pdf, svg, png, ...)

    >>> from reliure.engine import Engine
    >>> egn = Engine("preproc", "proc1", "proc2")
    >>> egn.preproc.setup(in_name="input", out_name="data")
    >>> egn.proc1.setup(in_name="data", out_name="gold_data")
    >>> egn.proc2.setup(in_name="input", out_name="silver_data")
    >>> # you can create
    >>> schema = engine_schema(egn, filename='docs/img/engine_schema', format='png')

    it create the following image :

    .. image:: /../_static/engine_schema.png

    You can specify which block output will be consider as engine output:

    >>> schema = engine_schema(egn, ["gold_data", "silver_data"], filename='docs/img/engine_schema_simple', format='png')

    .. image:: /../_static/engine_schema_simple.png

    Note that it is also possible to draw a pdf;

    >>> schema = engine_schema(egn, ["gold_data", "silver_data"], filename='docs/img/engine_schema_simple', format='pdf')
    """
    import graphviz as pgv
    #engine.validate()
    dg = pgv.Digraph(format=format)
    input_node_name = "in"
    output_node_name = "out"
    dg.node(input_node_name, label=input_node_name, shape="ellipse")
    block_source = {} # witch block is the source for witch data
    for e_in_name in engine.in_name:
        block_source[e_in_name] = input_node_name
    # creation des sommets
    for block in engine:
        dg.node(block.name, label=' %s ' % block.name, shape="box")
    # creation des liens
    for block in engine:
        for in_name in block.in_name:
            dg.edge(block_source[in_name], block.name,
                label=" %s " % in_name,
                #fontsize=10,
            )
        block_source[block.out_name] = block.name
    
    if out_names is None:
        out_names = set([block.out_name for block in engine])
    
    if len(out_names):
        dg.node(output_node_name, label=' %s ' % output_node_name, shape="ellipse")
        for out_name in out_names:
            if out_name not in block_source:
                raise ValueError("'%s' is not a generated data" % out_name)
            dg.edge(block_source[out_name], output_node_name,
                label=" %s " % out_name,
                #fontsize=10,
            )
    if filename:
        dg.render(filename)
    return dg