Beispiel #1
0
def _from_dotstring(dotstring):
    g = dot.graph_from_dot_data(dotstring)[0]

    # workaround for some badly parsed graph (pyparsing>=3.03)
    g.del_node('"\\n"')
    g.del_node('"\\n\\n"')

    g.set_bgcolor("transparent")
    for e in g.get_edges():
        if e.get_color() is None:
            e.set_color(getBlackInTheme())
    for n in g.get_nodes():
        if n.get_color() is None:
            n.set_color(getBlackInTheme())
        if n.get_fontcolor() is None:
            n.set_fontcolor(getBlackInTheme())
    return g
Beispiel #2
0
def BN2dot(bn,
           size=None,
           nodeColor=None,
           arcWidth=None,
           arcColor=None,
           cmapNode=None,
           cmapArc=None,
           showMsg=None):
    """
  create a pydot representation of the BN

  Parameters
  ----------
    bn : pyAgrum.BayesNet
      the Bayesian network
    size: str
      size of the rendered graph
    nodeColor: dict
      a nodeMap of values to be shown as color nodes (with special color for 0 and 1)
    arcWidth: dict
      a arcMap of values to be shown as bold arcs
    arcColor: dict
      a arcMap of values (between 0 and 1) to be shown as color of arcs
    cmapNode: ColorMap
      color map to show the vals of Nodes
    cmapArc: ColorMap
      color map to show the vals of Arcs
    showMsg: dict
      a nodeMap of values to be shown as tooltip

  Returns
  -------
    the desired representation of the Bayesian network
  """
    if cmapNode is None:
        cmapNode = plt.get_cmap(gum.config["notebook", "default_node_cmap"])

    if cmapArc is None:
        cmapArc = plt.get_cmap(gum.config["notebook", "default_arc_cmap"])

    # default
    maxarcs = 100
    minarcs = 0

    if arcWidth is not None:
        minarcs = min(arcWidth.values())
        maxarcs = max(arcWidth.values())

    dotobj = dot.Dot(graph_type='digraph', bgcolor="transparent")

    for n in bn.names():
        if nodeColor is None or n not in nodeColor:
            bgcol = gum.config["notebook", "default_node_bgcolor"]
            fgcol = gum.config["notebook", "default_node_fgcolor"]
            res = ""
        else:
            bgcol = gumcols.proba2bgcolor(nodeColor[n], cmapNode)
            fgcol = gumcols.proba2fgcolor(nodeColor[n], cmapNode)
            res = f" : {nodeColor[n] if showMsg is None else showMsg[n]:2.5f}"

        node = dot.Node('"' + n + '"',
                        style="filled",
                        fillcolor=bgcol,
                        fontcolor=fgcol,
                        tooltip=f'"({bn.idFromName(n)}) {n}{res}"')
        dotobj.add_node(node)

    for a in bn.arcs():
        if arcWidth is None:
            pw = 1
            av = ""
        else:
            if a in arcWidth:
                if maxarcs == minarcs:
                    pw = 1
                else:
                    pw = 0.1 + 5 * (arcWidth[a] - minarcs) / (maxarcs -
                                                              minarcs)
                av = arcWidth[a]
            else:
                pw = 1
                av = 1
        if arcColor is None:
            col = gumcols.getBlackInTheme()
        else:
            if a in arcColor:
                col = gumcols.proba2color(arcColor[a], cmapArc)
            else:
                col = gumcols.getBlackInTheme()

        edge = dot.Edge('"' + bn.variable(a[0]).name() + '"',
                        '"' + bn.variable(a[1]).name() + '"',
                        penwidth=pw,
                        color=col,
                        tooltip=f"{a} : {av}")
        dotobj.add_edge(edge)

    if size is None:
        size = gum.config["notebook", "default_graph_size"]

    # dynamic member makes pylink unhappy
    # pylint: disable=no-member
    dotobj.set_size(size)

    return dotobj
Beispiel #3
0
def BNinference2dot(bn,
                    size=None,
                    engine=None,
                    evs=None,
                    targets=None,
                    nodeColor=None,
                    arcWidth=None,
                    arcColor=None,
                    cmapNode=None,
                    cmapArc=None,
                    dag=None):
    """
  create a pydot representation of an inference in a BN

  Parameters
  ----------
    bn : pyAgrum.BayesNet
      the Bayesian network
    size: str
      size of the rendered graph
    engine:  pyAgrum.Inference
      inference algorithm used. If None, LazyPropagation will be used
    evs: dict
      map of evidence
    targets: set
      set of targets. If targets={} then each node is a target
    nodeColor: dict
      a nodeMap of values to be shown as color nodes (with special color for 0 and 1)
    arcWidth: dict
      a arcMap of values to be shown as bold arcs
    arcColor: dict
      a arcMap of values (between 0 and 1) to be shown as color of arcs
    cmapNode: ColorMap
      color map to show the vals of Nodes
    cmapArc: ColorMap
      color map to show the vals of Arcs
    dag : pyAgrum.DAG
      only shows nodes that have their id in the dag (and not in the whole BN)

  Returns
  -------
    the desired representation of the inference
  """
    if evs is None:
        evs = {}
    if targets is None:
        targets = {}
    if cmapNode is None:
        cmapNode = plt.get_cmap(gum.config["notebook", "default_node_cmap"])

    if cmapArc is None:
        cmapArc = plt.get_cmap(gum.config["notebook", "default_arc_cmap"])

    # defaukt
    maxarcs = 100
    minarcs = 0

    if arcWidth is not None:
        minarcs = min(arcWidth.values())
        maxarcs = max(arcWidth.values())

    startTime = time.time()
    if engine is None:
        ie = gum.LazyPropagation(bn)
    else:
        ie = engine
    ie.setEvidence(evs)
    ie.makeInference()
    stopTime = time.time()

    temp_dir = mkdtemp("", "tmp",
                       None)  # with TemporaryDirectory() as temp_dir:

    dotstr = "digraph structs {\n  fontcolor=\"" + \
             gumcols.getBlackInTheme() + "\";bgcolor=\"transparent\";"

    if gum.config["notebook", "show_inference_time"] == "True":
        dotstr += f"  label=\"Inference in {1000 * (stopTime - startTime):6.2f}ms\";\n"

    dotstr += '  node [fillcolor="' + gum.config["notebook", "default_node_bgcolor"] + \
              '", style=filled,color="' + \
              gum.config["notebook", "default_node_fgcolor"] + '"];' + "\n"
    dotstr += '  edge [color="' + gumcols.getBlackInTheme() + '"];' + "\n"

    showdag = bn.dag() if dag is None else dag
    for nid in showdag.nodes():
        name = bn.variable(nid).name()

        # defaults
        bgcol = gum.config["notebook", "default_node_bgcolor"]
        fgcol = gum.config["notebook", "default_node_fgcolor"]
        if len(targets) == 0 or name in targets or nid in targets:
            bgcol = gum.config["notebook", "figure_facecolor"]

        if nodeColor is not None:
            if name in nodeColor or nid in nodeColor:
                bgcol = gumcols.proba2bgcolor(nodeColor[name], cmapNode)
                fgcol = gumcols.proba2fgcolor(nodeColor[name], cmapNode)

        # 'hard' colour for evidence (?)
        if name in evs or nid in evs:
            bgcol = gum.config["notebook", "evidence_bgcolor"]
            fgcol = gum.config["notebook", "evidence_fgcolor"]

        colorattribute = f'fillcolor="{bgcol}", fontcolor="{fgcol}", color="#000000"'
        if len(targets) == 0 or name in targets or nid in targets:
            filename = temp_dir + \
                       hashlib.md5(name.encode()).hexdigest() + "." + \
                       gum.config["notebook", "graph_format"]
            proba_histogram.saveFigProba(ie.posterior(name),
                                         filename,
                                         bgcolor=bgcol)
            dotstr += f' "{name}" [shape=rectangle,image="{filename}",label="", {colorattribute}];\n'
        else:
            dotstr += f' "{name}" [{colorattribute}]'

    for a in showdag.arcs():
        (n, j) = a
        if arcWidth is None:
            pw = 1
            av = ""
        else:
            if (n, j) in arcWidth:
                if maxarcs == minarcs:
                    pw = 1
                else:
                    pw = 0.1 + 5 * (arcWidth[a] - minarcs) / (maxarcs -
                                                              minarcs)
                av = arcWidth[a]
            else:
                pw = 1
                av = ""

        if arcColor is None:
            col = gumcols.getBlackInTheme()
        else:
            if a in arcColor:
                col = gumcols.proba2color(arcColor[a], cmapArc)
            else:
                col = gumcols.getBlackInTheme()

        dotstr += f' "{bn.variable(n).name()}"->"{bn.variable(j).name()}" [penwidth="{pw}",tooltip="{a}:{av}",color="{col}"];'

    dotstr += '}'

    g = dot.graph_from_dot_data(dotstr)[0]

    # workaround for some badly parsed graph (pyparsing>=3.03)
    g.del_node('"\\n"')

    if size is None:
        size = gum.config["notebook", "default_graph_inference_size"]
    g.set_size(size)
    g.temp_dir = temp_dir

    return g
Beispiel #4
0
def graphDiff(bnref, bncmp, noStyle=False):
    """ Return a pydot graph that compares the arcs of bnref to bncmp.
  graphDiff allows bncmp to have less nodes than bnref. (this is not the case in GraphicalBNComparator.dotDiff())

  if noStyle is False use 4 styles (fixed in pyAgrum.config) :
    - the arc is common for both
    - the arc is common but inverted in _bn2
    - the arc is added in _bn2
    - the arc is removed in _bn2

  See graphDiffLegend() to add a legend to the graph.
  Warning
  -------
  if pydot is not installed, this function just returns None

  Returns
  -------
  pydot.Dot
    the result dot graph or None if pydot can not be imported
  """

    try:
        # pydot is optional
        # pylint: disable=import-outside-toplevel
        import pydot as dot
        import csv
        import pyAgrum.lib.bn2graph as ggr
    except ImportError:
        return None

    g = ggr.BN2dot(bnref)
    positions = {
        l[1]: f"{l[2]},{l[3]}!"
        for l in csv.reader(g.create(
            format="plain").decode("utf8").split("\n"),
                            delimiter=' ',
                            quotechar='"') if len(l) > 3 and l[0] == "node"
    }

    res = dot.Dot(graph_type='digraph',
                  bgcolor="transparent",
                  layout="fdp",
                  splines=True)
    for i1 in bnref.nodes():
        if bnref.variable(i1).name() in bncmp.names():
            res.add_node(
                dot.Node(f'"{bnref.variable(i1).name()}"',
                         style="filled",
                         fillcolor=gum.config["notebook",
                                              "graphdiff_correct_color"],
                         color=gumcols.getBlackInTheme(),
                         pos=positions[bnref.variable(i1).name()]))
        else:
            if not noStyle:
                res.add_node(
                    dot.Node(f'"{bnref.variable(i1).name()}"',
                             style="dashed",
                             fillcolor=gum.config["notebook",
                                                  "graphdiff_correct_color"],
                             color=gumcols.getBlackInTheme(),
                             pos=positions[bnref.variable(i1).name()]))
    if noStyle:
        for (i1, i2) in bncmp.arcs():
            n1 = bncmp.variable(i1).name()
            n2 = bncmp.variable(i2).name()
            res.add_edge(
                dot.Edge(f'"{n1}"',
                         f'"{n2}"',
                         style=gum.config["notebook",
                                          "graphdiff_correct_style"],
                         color=gum.config["notebook",
                                          "graphdiff_correct_color"],
                         constraint="false"))

    else:
        for (i1, i2) in bnref.arcs():
            n1 = bnref.variable(i1).name()
            n2 = bnref.variable(i2).name()

            # a node is missing
            if not (n1 in bncmp.names() and n2 in bncmp.names()):
                res.add_edge(
                    dot.Edge(f'"{n1}"',
                             f'"{n2}"',
                             style=gum.config["notebook",
                                              "graphdiff_missing_style"],
                             color=gum.config["notebook",
                                              "graphdiff_missing_color"]))
                continue

            keyarc = "graphdiff_correct"
            if bncmp.existsArc(n1, n2):  # arc is OK in BN2
                res.add_edge(
                    dot.Edge(f'"{n1}"',
                             f'"{n2}"',
                             style=gum.config["notebook",
                                              "graphdiff_correct_style"],
                             color=gum.config["notebook",
                                              "graphdiff_correct_color"]))
            elif bncmp.existsArc(n2, n1):  # arc is reversed in BN2
                res.add_edge(dot.Edge(f'"{n1}"', f'"{n2}"', style="invis"))
                res.add_edge(
                    dot.Edge(f'"{n2}"',
                             f'"{n1}"',
                             style=gum.config["notebook",
                                              "graphdiff_reversed_style"],
                             color=gum.config["notebook",
                                              "graphdiff_reversed_color"],
                             constraint="false"))
            else:  # arc is missing in BN2
                res.add_edge(
                    dot.Edge(f'"{n1}"',
                             f'"{n2}"',
                             style=gum.config["notebook",
                                              "graphdiff_missing_style"],
                             color=gum.config["notebook",
                                              "graphdiff_missing_color"]))

        for (i1, i2) in bncmp.arcs():
            n1 = bncmp.variable(i1).name()
            n2 = bncmp.variable(i2).name()
            if not bnref.existsArc(n1, n2) and not bnref.existsArc(
                    n2, n1):  # arc only in BN2
                res.add_edge(
                    dot.Edge(f'"{n1}"',
                             f'"{n2}"',
                             style=gum.config["notebook",
                                              "graphdiff_overflow_style"],
                             color=gum.config["notebook",
                                              "graphdiff_overflow_color"],
                             constraint="false"))

    return res
Beispiel #5
0
def LIMIDinference2dot(diag, size, engine, evs, targets):
    """
  create a pydot representation of an inference in a influence diagram

  Parameters
  ----------
  diag: pyAgrum.InfluenceDiagram
    the model
  size: float|str
    the size of the rendered graph
  engine: pyAgrum.InfluenceDiagramInference
    the inference algorithm used. If None, ShaferShenoyLIMIDInference will be used
  evs: Dict[str,str|int|List[float]]
    the evidence
  targets: Set[str]
    set of targetted variable. If targets={} then each node is a target

  Returns
  -------
  pydot.Dot
    the representation of the inference
  """
    startTime = time.time()
    if engine is None:
        ie = gum.ShaferShenoyLIMIDInference(diag)
    else:
        ie = engine
    ie.setEvidence(evs)
    ie.makeInference()
    stopTime = time.time()
    meu = ie.MEU()

    temp_dir = mkdtemp("", "tmp",
                       None)  # with TemporaryDirectory() as temp_dir:

    dotstr = "digraph structs {\n  fontcolor=\"" + \
             gumcols.getBlackInTheme() + "\";bgcolor=\"transparent\";"

    fmt = '.' + gum.config["influenceDiagram", "utility_visible_digits"] + 'f'
    if gum.config["influenceDiagram", "utility_show_loss"] == "True":
        titut = f'mEL {-meu["mean"]:{fmt}}'
    else:
        titut = f'MEU {meu["mean"]:{fmt}}'
    if gum.config["influenceDiagram", "utility_show_stdev"] == "True":
        titut += f' (stdev={math.sqrt(meu["variance"]):{fmt}})'

    slabel = f'label="{titut}'

    if gum.config["notebook", "show_inference_time"] == "True":
        slabel += f"\nInference in {1000 * (stopTime - startTime):6.2f}ms"
    dotstr += slabel + "\";\n"

    for nid in diag.nodes():
        name = diag.variable(nid).name()

        # defaults
        if diag.isChanceNode(nid):
            bgcolor = gum.config["influenceDiagram", "default_chance_bgcolor"]
            fgcolor = gum.config["influenceDiagram", "default_chance_fgcolor"]
            shape = gum.config["influenceDiagram", "chance_shape"]
        elif diag.isDecisionNode(nid):
            bgcolor = gum.config["influenceDiagram",
                                 "default_decision_bgcolor"]
            fgcolor = gum.config["influenceDiagram",
                                 "default_decision_fgcolor"]
            shape = gum.config["influenceDiagram", "decision_shape"]
        else:  # diag.isUtilityNode(nid):
            bgcolor = gum.config["influenceDiagram", "default_utility_bgcolor"]
            fgcolor = gum.config["influenceDiagram", "default_utility_fgcolor"]
            shape = gum.config["influenceDiagram", "utility_shape"]

        # 'hard' colour for evidence (?)
        if name in evs or nid in evs:
            bgcolor = gum.config["notebook", "evidence_bgcolor"]
            fgcolor = gum.config["notebook", "evidence_fgcolor"]

        styleattribute = 'style=filled, height=0,margin=0.1'
        colorattribute = f'fillcolor="{bgcolor}", fontcolor="{fgcolor}", color="#000000"'

        if not diag.isUtilityNode(nid):
            if len(targets) == 0 or name in targets or nid in targets:
                # shape="rectangle"
                filename = temp_dir + \
                           hashlib.md5(name.encode()).hexdigest() + "." + \
                           gum.config["notebook", "graph_format"]
                saveFigProba(ie.posterior(name),
                             filename,
                             bgcolor=bgcolor,
                             util=ie.posteriorUtility(nid),
                             txtcolor=fgcolor)
                dotstr += f' "{name}" [shape=rectangle,image="{filename}",label="", {colorattribute}];\n'
            else:
                dotstr += f' "{name}" [{colorattribute},shape={shape},{styleattribute}]'
        else:  # utility node
            mv = ie.meanVar(name)

            if gum.config["influenceDiagram", "utility_show_loss"] == "True":
                coef = -1
            else:
                coef = 1

            fmt = "." + gum.config["influenceDiagram",
                                   "utility_visible_digits"] + "f"
            labut = f'{name} : {coef * mv["mean"]:{fmt}}'
            if gum.config["influenceDiagram", "utility_show_stdev"] == "True":
                labut += f' ({math.sqrt(mv["variance"]):{fmt}})'

            dotstr += f' "{name}" [label="{labut}",{colorattribute},{styleattribute},shape={shape}]'

    # arcs
    dotstr += "\n"
    for node in diag.nodes():
        for chi in diag.children(node):
            dotstr += '  "' + diag.variable(node).name() + '"->"' + \
                      diag.variable(chi).name() + '"'
            if diag.isDecisionNode(chi):
                dotstr += f' [style="{gum.config["influenceDiagram", "decision_arc_style"]}"]'
            elif diag.isUtilityNode(chi):
                dotstr += f' [style="{gum.config["influenceDiagram", "utility_arc_style"]}"]'
            dotstr += ";\n"
    dotstr += "}"

    g = dot.graph_from_dot_data(dotstr)[0]

    # workaround for some badly parsed graph (pyparsing>=3.03)
    g.del_node('"\\n"')

    if size is None:
        size = gum.config["influenceDiagram", "default_id_inference_size"]
    g.set_size(size)
    g.temp_dir = temp_dir

    return g
Beispiel #6
0
def MN2UGdot(mn,
             size="4",
             nodeColor=None,
             edgeWidth=None,
             edgeColor=None,
             cmapNode=None,
             cmapEdge=None,
             showMsg=None):
    """
  Create a pydot representation of the Markov Network as an undirected graph

  Parameters
  ----------
  mn : pyAgrum.MarkovNet
    The Markov network
  size : int |str
    Size of the rendered graph
  nodeColor : Dict[int,float]
    a nodeMap of values (between 0 and 1) to be shown as color of nodes (with special colors for 0 and 1)
  edgeWidth : Dict[Tuple(int,int),float]
    a edgeMap of values to be shown as width of edges
  edgeColor: Dict[Tuple(int,int),float]
    a edgeMap of values to be shown as color of edges
  cmapNode : matplotlib.color.colormap
    color map to show the vals of Nodes
  cmapEdge
    color map to show the vals of Edges.
  showMsg : Dict[int,str]
     a nodeMap of values to be shown as tooltip

  Returns
  -------
  pydot.Dot
    the desired representation of the MN as a dot graph
  """
    if cmapNode is None:
        cmapNode = plt.get_cmap(gum.config["notebook", "default_node_cmap"])

    if cmapEdge is None:
        cmapEdge = plt.get_cmap(gum.config["notebook", "default_edge_cmap"])

    # default
    maxedges = 100
    minedges = 0

    if edgeWidth is not None:
        minedges = min(edgeWidth.values())
        maxedges = max(edgeWidth.values())

    graph = dot.Dot(graph_type='graph', bgcolor="transparent")

    for n in mn.names():
        if nodeColor is None or n not in nodeColor:
            bgcol = gum.config["notebook", "default_node_bgcolor"]
            fgcol = gum.config["notebook", "default_node_fgcolor"]
            res = ""
        else:
            bgcol = gumcols.proba2bgcolor(nodeColor[n], cmapNode)
            fgcol = gumcols.proba2fgcolor(nodeColor[n], cmapNode)
            res = f" : {nodeColor[n] if showMsg is None else showMsg[n]:2.5f}"

        node = dot.Node('"' + n + '"',
                        style="filled",
                        fillcolor=bgcol,
                        fontcolor=fgcol,
                        tooltip=f'"({mn.idFromName(n)}) {n}{res}"')
        graph.add_node(node)

    for a in mn.edges():
        if edgeWidth is None:
            pw = 1
            av = ""
        else:
            if a in edgeWidth:
                if maxedges == minedges:
                    pw = 1
                else:
                    pw = 0.1 + 5 * (edgeWidth[a] - minedges) / (maxedges -
                                                                minedges)
                av = edgeWidth[a]
            else:
                pw = 1
                av = 1
        if edgeColor is None:
            col = gumcols.getBlackInTheme()
        else:
            if a in edgeColor:
                col = gumcols.proba2color(edgeColor[a], cmapEdge)
            else:
                col = gumcols.getBlackInTheme()

        edge = dot.Edge('"' + mn.variable(a[0]).name() + '"',
                        '"' + mn.variable(a[1]).name() + '"',
                        penwidth=pw,
                        color=col,
                        tooltip=f"{a} : {av}")
        graph.add_edge(edge)

    if size is None:
        size = gum.config["notebook", "default_graph_size"]
    graph.set_size(size)
    return graph
Beispiel #7
0
def MNinference2FactorGraphdot(mn,
                               size=None,
                               engine=None,
                               evs=None,
                               targets=None,
                               nodeColor=None,
                               factorColor=None,
                               cmapNode=None):
    """
  create a pydot representation of an inference in a MN as an factor graph

  :param pyAgrum.MarkovNet mn:
  :param string size: size of the rendered graph
  :param pyAgrum Inference engine: inference algorithm used. If None, ShaferShenoyMNInference will be used
  :param dictionnary evs: map of evidence
  :param set targets: set of targets. If targets={} then each node is a target
  :param nodeColor: a nodeMap of values to be shown as color nodes (with special color for 0 and 1)
  :param cmapNode: color map to show the vals of Nodes

  :return: the desired representation of the inference
  """
    if evs is None:
        evs = {}
    if targets is None:
        targets = {}
    if cmapNode is None:
        cmapNode = plt.get_cmap(gum.config["notebook", "default_node_cmap"])

    startTime = time.time()
    if engine is None:
        ie = gum.ShaferShenoyMNInference(mn)
    else:
        ie = engine
    ie.setEvidence(evs)
    ie.makeInference()
    stopTime = time.time()

    from tempfile import mkdtemp
    temp_dir = mkdtemp("", "tmp",
                       None)  # with TemporaryDirectory() as temp_dir:

    dotstr = "graph {\n  layout=\"neato\";\n  fontcolor=\"" + \
             gumcols.getBlackInTheme() + "\";bgcolor=\"transparent\";"

    if gum.config["notebook", "show_inference_time"] == "True":
        dotstr += f'  label="Inference in {1000 * (stopTime - startTime):6.2f}ms";\n'

    dotstr += '  node [fillcolor="' + gum.config["notebook", 'default_node_bgcolor'] + \
              '", style=filled,color="' + \
              gum.config["notebook", "default_node_fgcolor"] + '"];' + "\n"
    dotstr += '  edge [color="' + gumcols.getBlackInTheme() + '"];' + "\n"

    for nid in mn.nodes():
        name = mn.variable(nid).name()

        # defaults
        bgcol = gum.config["notebook", "default_node_bgcolor"]
        fgcol = gum.config["notebook", "default_node_fgcolor"]
        if len(targets) == 0 or name in targets or nid in targets:
            bgcol = gum.config["notebook", "figure_facecolor"]

        if nodeColor is not None:
            if name in nodeColor or nid in nodeColor:
                bgcol = gumcols.proba2bgcolor(nodeColor[name], cmapNode)
                fgcol = gumcols.proba2fgcolor(nodeColor[name], cmapNode)

        # 'hard' colour for evidence (?)
        if name in evs or nid in evs:
            bgcol = gum.config["notebook", "evidence_bgcolor"]
            fgcol = gum.config["notebook", "evidence_fgcolor"]

        colorattribute = f'fillcolor="{bgcol}", fontcolor="{fgcol}", color="#000000"'
        if len(targets) == 0 or name in targets or nid in targets:
            filename = temp_dir + \
                       hashlib.md5(name.encode()).hexdigest() + "." + \
                       gum.config["notebook", "graph_format"]
            saveFigProba(ie.posterior(name), filename, bgcolor=bgcol)
            dotstr += f' "{name}" [shape=rectangle,image="{filename}",label="", {colorattribute}];\n'
        else:
            dotstr += f' "{name}" [shape=rectangle,margin=0.04,width=0,height=0,{colorattribute}];\n'

    def factorname(f):
        return '"f' + "#".join(map(str, sorted(list(f)))) + '"'

    for f in mn.factors():
        if factorColor is None:
            bgcol = gum.config["factorgraph", "default_factor_bgcolor"]
        else:
            bgcol = gumcols.proba2bgcolor(factorColor(f), cmapNode)
        dotstr += f'  {factorname(f)} [style=filled,fillcolor={bgcol},shape=point,width=0.1,height=0.1];\n'

    for f in mn.factors():
        col = gumcols.getBlackInTheme()
        for n in f:
            dotstr += f' {factorname(f)}->"{mn.variable(n).name()}" [tooltip="{f}:{n}",color="{col}",fillcolor="{bgcol}",len="{gum.config["factorgraph", "edge_length_inference"]}"];\n'
    dotstr += '}'

    g = dot.graph_from_dot_data(dotstr)[0]

    # workaround for some badly parsed graph (pyparsing>=3.03)
    g.del_node('"\\n"')

    if size is None:
        size = gum.config["notebook", "default_graph_inference_size"]
    g.set_size(size)
    g.temp_dir = temp_dir

    return g
Beispiel #8
0
def MNinference2UGdot(mn,
                      size=None,
                      engine=None,
                      evs=None,
                      targets=None,
                      nodeColor=None,
                      factorColor=None,
                      arcWidth=None,
                      arcColor=None,
                      cmapNode=None,
                      cmapArc=None,
                      view=None):
    """
  create a pydot representation of an inference in a MN as an UG

  :param pyAgrum.MarkovNet mn:
  :param string size: size of the rendered graph
  :param pyAgrum Inference engine: inference algorithm used. If None, ShaferShenoyMNInference will be used
  :param dictionnary evs: map of evidence
  :param set targets: set of targets. If targets={} then each node is a target
  :param nodeColor: a nodeMap of values to be shown as color nodes (with special color for 0 and 1)
  :param arcWidth: a arcMap of values to be shown as bold arcs
  :param arcColor: a arcMap of values (between 0 and 1) to be shown as color of arcs
  :param cmapNode: color map to show the vals of Nodes
  :param cmapArc: color map to show the vals of Arcs

  :return: the desired representation of the inference
  """
    if evs is None:
        evs = {}
    if targets is None:
        targets = {}

    if cmapNode is None:
        cmapNode = plt.get_cmap(gum.config["notebook", "default_node_cmap"])

    if cmapArc is None:
        cmapArc = plt.get_cmap(gum.config["notebook", "default_arc_cmap"])

    # default
    minarcs = 0
    maxarcs = 100

    if arcWidth is not None:
        minarcs = min(arcWidth.values())
        maxarcs = max(arcWidth.values())

    startTime = time.time()
    if engine is None:
        ie = gum.ShaferShenoyMNInference(mn)
    else:
        ie = engine
    ie.setEvidence(evs)
    ie.makeInference()
    stopTime = time.time()

    from tempfile import mkdtemp
    temp_dir = mkdtemp("", "tmp",
                       None)  # with TemporaryDirectory() as temp_dir:

    dotstr = "graph structs {\n  fontcolor=\"" + \
             gumcols.getBlackInTheme() + "\";bgcolor=\"transparent\";"

    if gum.config["notebook", "show_inference_time"] == "True":
        dotstr += f'  label="Inference in {1000 * (stopTime - startTime):6.2f}ms";\n'

    dotstr += '  node [fillcolor="' + gum.config["notebook", "default_node_bgcolor"] + \
              '", style=filled,color="' + \
              gum.config["notebook", "default_node_fgcolor"] + '"];' + "\n"
    dotstr += '  edge [color="' + gumcols.getBlackInTheme() + '"];' + "\n"

    for nid in mn.nodes():
        name = mn.variable(nid).name()

        # defaults
        bgcol = gum.config["notebook", "default_node_bgcolor"]
        fgcol = gum.config["notebook", "default_node_fgcolor"]
        if len(targets) == 0 or name in targets or nid in targets:
            bgcol = gum.config["notebook", "figure_facecolor"]

        if nodeColor is not None:
            if name in nodeColor or nid in nodeColor:
                bgcol = gumcols.proba2bgcolor(nodeColor[name], cmapNode)
                fgcol = gumcols.proba2fgcolor(nodeColor[name], cmapNode)

        # 'hard' colour for evidence (?)
        if name in evs or nid in evs:
            bgcol = gum.config["notebook", "evidence_bgcolor"]
            fgcol = gum.config["notebook", "evidence_fgcolor"]

        colorattribute = f'fillcolor="{bgcol}", fontcolor="{fgcol}", color="#000000"'

        if len(targets) == 0 or name in targets or nid in targets:
            filename = temp_dir + \
                       hashlib.md5(name.encode()).hexdigest() + "." + \
                       gum.config["notebook", "graph_format"]
            saveFigProba(ie.posterior(name), filename, bgcolor=bgcol)
            dotstr += f' "{name}" [shape=rectangle,image="{filename}",label="", {colorattribute}];\n'
        else:
            dotstr += f' "{name}" [{colorattribute}]'

    for a in mn.edges():
        (n, j) = a
        if arcWidth is None:
            pw = 1
            av = ""
        else:
            if (n, j) in arcWidth:
                if maxarcs == minarcs:
                    pw = 1
                else:
                    pw = 0.1 + 5 * (arcWidth[a] - minarcs) / (maxarcs -
                                                              minarcs)
                av = arcWidth[a]
            else:
                pw = 1
                av = ""

        if arcColor is None:
            col = gumcols.getBlackInTheme()
        else:
            if a in arcColor:
                col = gumcols.proba2color(arcColor[a], cmapArc)
            else:
                col = gumcols.getBlackInTheme()

        dotstr += f' "{mn.variable(n).name()}"--"{mn.variable(j).name()}" [penwidth="{pw}",tooltip="{a}:{av}",color="{col}"];'
    dotstr += '}'

    g = dot.graph_from_dot_data(dotstr)[0]

    # workaround for some badly parsed graph (pyparsing>=3.03)
    g.del_node('"\\n"')

    if size is None:
        size = gum.config["notebook", "default_graph_inference_size"]
    g.set_size(size)
    g.temp_dir = temp_dir

    return g
Beispiel #9
0
def MN2FactorGraphdot(mn,
                      size=None,
                      nodeColor=None,
                      factorColor=None,
                      cmapNode=None,
                      showMsg=None):
    """
  Create a pydot representation of the Markov Network as a factor graph

  Parameters
  ----------
  mn: pyAgrum.MarkovNet
    the model
  size: float|str
    the size of the rendered graph
  nodeColor: Dict[str,float]
    a nodeMap of values (between 0 and 1) to be shown as color of nodes (with special colors for 0 and 1)
  factorColor:
    a function returning a value (between 0 and 1) to be shown as a color of factor.
  cmapNode: matplotlib.colors.Colormap
    colormap for nodes
  showMsg: Dict[str,str]
    a nodeMap of values to be shown as tooltip

  Returns
  -------
  pydot.Dot
    the desired representation of the MN as a dot graph
  """
    if cmapNode is None:
        cmapNode = plt.get_cmap(gum.config["notebook", "default_node_cmap"])

    graph = dot.Dot(graph_type='graph', bgcolor="transparent", layout="neato")

    for n in mn.names():
        if nodeColor is None or n not in nodeColor:
            bgcol = gum.config["factorgraph", "default_node_bgcolor"]
            fgcol = gum.config["factorgraph", "default_node_fgcolor"]
            res = ""
        else:
            bgcol = gumcols.proba2bgcolor(nodeColor[n], cmapNode)
            fgcol = gumcols.proba2fgcolor(nodeColor[n], cmapNode)
            res = f" : {nodeColor[n] if showMsg is None else showMsg[n]:2.5f}"

        node = dot.Node('"' + n + '"',
                        style="filled",
                        fillcolor=bgcol,
                        fontcolor=fgcol,
                        shape="rectangle",
                        margin=0.04,
                        width=0,
                        height=0,
                        tooltip=f'"({mn.idFromName(n)}) {n}{res}"')
        graph.add_node(node)

    def factorname(factor):
        return '"f' + "#".join(map(str, sorted(list(factor)))) + '"'

    for f in mn.factors():
        if factorColor is None:
            bgcol = gum.config["factorgraph", "default_factor_bgcolor"]
        else:
            bgcol = gumcols.proba2bgcolor(factorColor(f), cmapNode)
        node = dot.Node(factorname(f),
                        style="filled",
                        fillcolor=bgcol,
                        shape="point",
                        width=0.1,
                        height=0.1)
        graph.add_node(node)

    for f in mn.factors():
        for n in f:
            edge = dot.Edge(factorname(f),
                            '"' + mn.variable(n).name() + '"',
                            color=gumcols.getBlackInTheme(),
                            len=gum.config["factorgraph", "edge_length"])
            graph.add_edge(edge)

    if size is None:
        size = gum.config["notebook", "default_graph_size"]
    graph.set_size(size)
    return graph