code: def render_diagram(root_task, out_base, max_param_len=20, horizontal=False, colored=False):
      import re
      import codecs
      import subprocess
      from ozelot import config
      from ozelot.etl.tasks import get_task_name, get_task_param_string
      lines = [u"digraph G {"]
      if horizontal:
          lines.append(u"rankdir=LR;")
      def get_id(task):
          s = get_task_name(task) + "_" + get_task_param_string(task)
          return re.sub(r'\W+', '', re.sub(' ', '_', s))
      existing_nodes = set()
      existing_edges = set()
      def _build(task, parent_id=None):
          tid = get_id(task)
          if tid not in existing_nodes:
              params = task.to_str_params()
              param_list = ""
              for k, v in params.items():
                  if len(v) > max_param_len:
                      v = v[:max_param_len] + "..."
                  param_list += "<TR><TD ALIGN=\"LEFT\">" \
                                "<FONT POINT-SIZE=\"10\">{:s}</FONT>" \
                                "</TD><TD ALIGN=\"LEFT\">" \
                                "<FONT POINT-SIZE=\"10\">{:s}</FONT>" \
                                "</TD></TR>".format(k, v)
              label = "<TABLE BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"1\">" \
                      "<TR><TD COLSPAN=\"2\" ALIGN=\"CENTER\">" \
                      "<FONT POINT-SIZE=\"12\">{:s}</FONT>" \
                      "</TD></TR>" \
                      "".format(get_task_name(task)) + param_list + "</TABLE>"
              style = getattr(task, 'diagram_style', [])
              if colored:
                  color = ', color="{:s}"'.format("green" if task.complete() else "red")
              else:
                  color = ''
              lines.append(u"{name:s} [label=< {label:s} >, shape=\"rect\" {color:s}, style=\"{style:s}\"];\n"
                           u"".format(name=tid,
                                      label=label,
                                      color=color,
                                      style=','.join(style)))
              existing_nodes.add(tid)
              for req in task.requires():
                  _build(req, parent_id=tid)
          if parent_id is not None and (tid, parent_id) not in existing_edges:
              lines.append(u"{source:s} -> {target:s};\n".format(source=tid, target=parent_id))
      _build(root_task)
      lines.append(u"}")
      with codecs.open(out_base + '.dot', 'w', encoding='utf-8') as f:
          f.write(u"\n".join(lines))
      if not hasattr(config, 'DOT_EXECUTABLE'):
          raise RuntimeError("Please configure the 'DOT_EXECUTABLE' variable in your 'project_config.py'")
      if not os.path.exists(config.DOT_EXECUTABLE):
          raise IOError("Could not find file pointed to by 'DOT_EXECUTABLE': " + str(config.DOT_EXECUTABLE))
      subprocess.check_call([
          config.DOT_EXECUTABLE,
          '-T', 'png',
          '-o', out_base + '.png',
                out_base + '.dot'
      ])