interactive notebooks

Creative Commons License

aGrUM

interactive online version

pyAgrum can easily interact with other applications. In this notebook, we propose for example some application tracks with notebook ipywidgets to make the exploration of graphical models and their inferences more interactive.

In [1]:
import pyAgrum as gum
import pyAgrum.lib.notebook as gnb

Listeners and progress bars

In [2]:
import glob
import os.path
from tqdm.auto import tqdm

class TqdmProgressBarLoadListener:
    def __init__(self,filename:str):
        self.pbar=tqdm(total=100,
                      desc=filename,
                      bar_format='{desc}: {percentage:3.0f}%|{bar}|')
    def update(self,progress):
        if progress==200:
            self.pbar.close()
        else:
            self.pbar.update()
            self.pbar.display()


bns={}
for ext in ['dsl','bif']:
    for name in glob.glob(f"res/*.{ext}"):
        progbar=TqdmProgressBarLoadListener(name)
        bns[os.path.basename(name)]=gum.loadBN(name,listeners=[lambda progress:progbar.update(progress)])

Which should give you something like

a progess bar

Animated graphs

ipywidget can be used with different types of objects. Let’s say that you have a class that show the arcs of a Bayesian network only the mutual information of this arc is above a certain threshold:

In [3]:
import pydot as dot

class InformationViewer:
    def __init__(self,bn:gum.BayesNet):
        self.bn=bn

        ie=gum.LazyPropagation(bn)
        self._min=float("inf")
        self._max=float("-inf")
        self._arcs={}
        for x,y in bn.arcs():
            nameX=bn.variable(x).name()
            nameY=bn.variable(y).name()
            ie.addJointTarget({nameX,nameY})
            info=gum.InformationTheory(ie,[nameX],[nameY])
            m=info.mutualInformationXY()
            if self._min>m: self._min=m
            if self._max<m: self._max=m
            self._arcs[x,y]=m

    def min(self):
        return self._min

    def max(self):
        return self._max

    def showBN(self,minVal:float=0):
        graph=dot.Dot(graph_type="digraph",bgcolor="transparent")
        bgcol = gum.config["notebook", "default_node_bgcolor"]
        fgcol = gum.config["notebook", "default_node_fgcolor"]
        for n in self.bn.names():
            graph.add_node(dot.Node('"' + n + '"', style="filled",
                                    fillcolor=bgcol,
                                    fontcolor=fgcol))
        for x,y in self.bn.arcs():
            graph.add_edge(dot.Edge('"' + self.bn.variable(x).name() + '"',
                                    '"' + self.bn.variable(y).name() + '"',
                                    style="invis" if self._arcs[x,y]<minVal else ""))


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

view=InformationViewer(bns['alarm.dsl'])
print(f"min={view.min()} ,max={view.max()}")
gnb.sideBySide(view.showBN(0.3),view.showBN(0.5),
              captions=["BN filtered by $MI>0.3$","BN filtered by $MI>0.5$"])
min=7.940532588369736e-06 ,max=0.8850119269966232
G ANAPHYLAXIS ANAPHYLAXIS TPR TPR INSUFFANESTH INSUFFANESTH CATECHOL CATECHOL PULMEMBOLUS PULMEMBOLUS PAP PAP SHUNT SHUNT FIO2 FIO2 PVSAT PVSAT HR HR DISCONNECT DISCONNECT VENTTUBE VENTTUBE HYPOVOLEMIA HYPOVOLEMIA STROKEVOLUME STROKEVOLUME HYPOVOLEMIA->STROKEVOLUME LVEDVOLUME LVEDVOLUME HYPOVOLEMIA->LVEDVOLUME CO CO BP BP CO->BP VENTALV VENTALV ARTCO2 ARTCO2 VENTALV->ARTCO2 VENTALV->PVSAT HREKG HREKG CVP CVP EXPCO2 EXPCO2 HRSAT HRSAT HR->HRSAT HRBP HRBP HR->HRBP STROKEVOLUME->CO PRESS PRESS VENTLUNG VENTLUNG MINVOL MINVOL LVFAILURE LVFAILURE HISTORY HISTORY PCWP PCWP KINKEDTUBE KINKEDTUBE MINVOLSET MINVOLSET VENTMACH VENTMACH MINVOLSET->VENTMACH SAO2 SAO2 LVEDVOLUME->CVP LVEDVOLUME->PCWP INTUBATION INTUBATION VENTLUNG->VENTALV VENTLUNG->EXPCO2 ERRCAUTER ERRCAUTER ERRCAUTER->HRSAT VENTMACH->VENTTUBE ERRLOWOUTPUT ERRLOWOUTPUT
BN filtered by $MI>0.3$
G ANAPHYLAXIS ANAPHYLAXIS TPR TPR INSUFFANESTH INSUFFANESTH CATECHOL CATECHOL PULMEMBOLUS PULMEMBOLUS PAP PAP SHUNT SHUNT FIO2 FIO2 PVSAT PVSAT HR HR DISCONNECT DISCONNECT VENTTUBE VENTTUBE HYPOVOLEMIA HYPOVOLEMIA STROKEVOLUME STROKEVOLUME LVEDVOLUME LVEDVOLUME CO CO BP BP VENTALV VENTALV ARTCO2 ARTCO2 HREKG HREKG CVP CVP EXPCO2 EXPCO2 HRSAT HRSAT HRBP HRBP STROKEVOLUME->CO PRESS PRESS VENTLUNG VENTLUNG MINVOL MINVOL LVFAILURE LVFAILURE HISTORY HISTORY PCWP PCWP KINKEDTUBE KINKEDTUBE MINVOLSET MINVOLSET VENTMACH VENTMACH SAO2 SAO2 LVEDVOLUME->CVP LVEDVOLUME->PCWP INTUBATION INTUBATION VENTLUNG->VENTALV VENTLUNG->EXPCO2 ERRCAUTER ERRCAUTER VENTMACH->VENTTUBE ERRLOWOUTPUT ERRLOWOUTPUT
BN filtered by $MI>0.5$

Now we can use this class for animation :

In [4]:
import ipywidgets as widgets
def interactive_view(threshold:float):
    return view.showBN(threshold)
widgets.interact(interactive_view,threshold=(view.min(),
                                             view.max(),
                                             (view.max()-view.min())/100.0));

Which should give you something like

a progess bar

Vizualizing evidence impact

In [5]:
from ipywidgets import interact, fixed

bn = bns['asia.bif']

asia = list(bn.variableFromName("visit_to_Asia").labels())
smoking = list(bn.variableFromName("smoking").labels())
XraY = list(bn.variableFromName("positive_XraY").labels())
cig_ped_day = gum.RangeVariable("cigarettes_per_day","cigarettes_per_day in [0, 10]?",0,10)
bn.add(cig_ped_day)

@interact(bn=fixed(bn), visit_to_Asia=asia, smoking=smoking, positive_XraY=XraY, smoked_cigarettes=(cig_ped_day.minVal(), cig_ped_day.maxVal(), 1))
def evidence_impact(bn, visit_to_Asia, smoking, positive_XraY, smoked_cigarettes):
    evs = {"visit_to_Asia":visit_to_Asia, "smoking":smoking, "positive_XraY":positive_XraY, "cigarettes_per_day":smoked_cigarettes}
    gnb.showInference(bn, evs=evs)