in dowhy/causal_graph.py [0:0]
def build_graph(self, common_cause_names, instrument_names,
effect_modifier_names, mediator_names):
""" Creates nodes and edges based on variable names and their semantics.
Currently only considers the graphical representation of "direct" effect modifiers. Thus, all effect modifiers are assumed to be "direct" unless otherwise expressed using a graph. Based on the taxonomy of effect modifiers by VanderWheele and Robins: "Four types of effect modification: A classification based on directed acyclic graphs. Epidemiology. 2007."
"""
for treatment in self.treatment_name:
self._graph.add_node(treatment, observed="yes", penwidth=2)
for outcome in self.outcome_name:
self._graph.add_node(outcome, observed="yes", penwidth=2)
for treatment, outcome in itertools.product(self.treatment_name, self.outcome_name):
# adding penwidth to make the edge bold
self._graph.add_edge(treatment, outcome, penwidth=2)
# Adding common causes
if common_cause_names is not None:
for node_name in common_cause_names:
for treatment, outcome in itertools.product(self.treatment_name, self.outcome_name):
self._graph.add_node(node_name, observed="yes")
self._graph.add_edge(node_name, treatment)
self._graph.add_edge(node_name, outcome)
# Adding instruments
if instrument_names:
if type(instrument_names[0]) != tuple:
if len(self.treatment_name) > 1:
self.logger.info("Assuming Instrument points to all treatments! Use tuples for more granularity.")
for instrument, treatment in itertools.product(instrument_names, self.treatment_name):
self._graph.add_node(instrument, observed="yes")
self._graph.add_edge(instrument, treatment)
else:
for instrument, treatment in itertools.product(instrument_names):
self._graph.add_node(instrument, observed="yes")
self._graph.add_edge(instrument, treatment)
# Adding effect modifiers
if effect_modifier_names is not None:
for node_name in effect_modifier_names:
if node_name not in common_cause_names:
for outcome in self.outcome_name:
self._graph.add_node(node_name, observed="yes")
# Assuming the simple form of effect modifier
# that directly causes the outcome.
self._graph.add_edge(node_name, outcome)
#self._graph.add_edge(node_name, outcome, style = "dotted", headport="s", tailport="n")
#self._graph.add_edge(outcome, node_name, style = "dotted", headport="n", tailport="s") # TODO make the ports more general so that they apply not just to top-bottom node configurations
if mediator_names is not None:
for node_name in mediator_names:
for treatment, outcome in itertools.product(self.treatment_name, self.outcome_name):
self._graph.add_node(node_name, observed="yes")
self._graph.add_edge(treatment, node_name)
self._graph.add_edge(node_name, outcome)
return self._graph