class_docstr: Class for creating and modifying the causal graph.
  
  Accepts a networkx DiGraph, a :py:class:`ProbabilisticCausalModel <dowhy.gcm.ProbabilisticCausalModel`, a graph string (or a text file) in gml format (preferred) or dot format. Graphviz-like attributes can be set for edges and nodes. E.g. style="dashed" as an edge attribute ensures that the edge is drawn with a dashed line.
  
   If a graph string is not given, names of treatment, outcome, and confounders, instruments and effect modifiers (if any) can be provided to create the graph.
class_docstr_tok: ["Class","for","creating","and","modifying","the","causal","graph",".","Accepts","a","networkx","DiGraph",",","a",":","py",":","class",":","`","ProbabilisticCausalModel","<","dowhy.gcm.ProbabilisticCausalModel","`",",","a","graph","string","(","or","a","text","file",")","in","gml","format","(","preferred",")","or","dot","format",".","Graphviz-like","attributes","can","be","set","for","edges","and","nodes",".","E.g",".","style=","''","dashed","''","as","an","edge","attribute","ensures","that","the","edge","is","drawn","with","a","dashed","line",".","If","a","graph","string","is","not","given",",","names","of","treatment",",","outcome",",","and","confounders",",","instruments","and","effect","modifiers","(","if","any",")","can","be","provided","to","create","the","graph","."]
docstr: 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."
docstr_tok: ["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",".","''"]
code: 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
              self._graph.nodes[node_name]["effectmodifier"] = True
      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
  
imports: import itertools
  import logging
  import re
  import networkx
  from dowhy.gcm.causal_models import ProbabilisticCausalModel
  from dowhy.utils.api import parse_state
  from dowhy.utils.graph_operations import daggity_to_dot
  from dowhy.utils.plotting import plot
label_desc: Use image node_id 3 for calling the CausalGraph obj's underlying member method code with example usage: obj.build_graph(common_cause_names, instrument_names, effect_modifier_names, mediator_names) and returns: self