prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  d3viz doesn't work for some graphs
  Sometimes d3viz doesn't work for me - empty graph is displayed, and there is an error message in JS console. I tried to reduce it to a minimal example
  
  ``` py
  import os    
  os.environ['THEANO_FLAGS'] = "device=gpu0,floatX=float32" #,optimizer=fast_compile"
  
  import numpy as np
  from lasagne.updates import adam
  from theano import tensor as T, shared, function
  import theano.d3viz as d3v
  
  def show_d3(g):
      d3v.d3viz(g, 'example.html')
      from IPython.display import IFrame
      return IFrame('example.html', width=800, height=500)
  
  x = T.fvector()
  W = shared(np.zeros((10, 5), dtype=np.float32))
  b = shared(np.zeros((10,), dtype=np.float32))
  y_true = T.fvector()
  
  y = T.nnet.sigmoid(T.dot(x, W) + b)
  cost = T.sqrt(((y - y_true)**2).sum())
  
  updates = adam(cost, [W])  # no b!
  f_cost = function([x, y_true], cost, updates=updates)
  show_d3(f_cost)
  ```
  
  (IPython notebook: https://gist.github.com/kmike/13b0fb747dccd4f2f1e44789a9cb832c).
  This is brittle: if `adam` is replaced with any other training method from Lasagne (or if a simple SGD is implemented manually) chart works; if `T.sqrt` is removed from `cost` expression chart works; if `T.nnet sigmoid` is removed from `y` expression chart works; if `b` is added to adam updates chart works; if `optimizer=fast_compile` is added to THEANO_FLAGS chart works.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `theano/d3viz/d3viz.py`
  Content:
  ```
  1 """Dynamic visualization of Theano graphs.
  2 
  3 Author: Christof Angermueller <cangermueller@gmail.com>
  4 """
  5 from __future__ import absolute_import, print_function, division
  6 
  7 import os
  8 import shutil
  9 import re
  10 import six
  11 from six import iteritems
  12 
  13 from theano.d3viz.formatting import PyDotFormatter
  14 
  15 __path__ = os.path.dirname(os.path.realpath(__file__))
  16 
  17 
  18 def replace_patterns(x, replace):
  19     """Replace `replace` in string `x`.
  20 
  21     Parameters
  22     ----------
  23     s : str
  24         String on which function is applied
  25     replace : dict
  26         `key`, `value` pairs where key is a regular expression and `value` a
  27         string by which `key` is replaced
  28     """
  29     for from_, to in iteritems(replace):
  30         x = x.replace(str(from_), str(to))
  31     return x
  32 
  33 
  34 def escape_quotes(s):
  35     """Escape quotes in string.
  36 
  37     Parameters
  38     ----------
  39     s : str
  40         String on which function is applied
  41     """
  42     s = re.sub(r'''(['"])''', r'\\\1', s)
  43     return s
  44 
  45 
  46 def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
  47     """Create HTML file with dynamic visualizing of a Theano function graph.
  48 
  49     In the HTML file, the whole graph or single nodes can be moved by drag and
  50     drop. Zooming is possible via the mouse wheel. Detailed information about
  51     nodes and edges are displayed via mouse-over events. Node labels can be
  52     edited by selecting Edit from the context menu.
  53 
  54     Input nodes are colored in green, output nodes in blue. Apply nodes are
  55     ellipses, and colored depending on the type of operation they perform. Red
  56     ellipses are transfers from/to the GPU (ops with names GpuFromHost,
  57     HostFromGpu).
  58 
  59     Edges are black by default. If a node returns a view of an
  60     input, the input edge will be blue. If it returns a destroyed input, the
  61     edge will be red.
  62 
  63     Parameters
  64     ----------
  65     fct : theano.compile.function_module.Function
  66         A compiled Theano function, variable, apply or a list of variables.
  67     outfile : str
  68         Path to output HTML file.
  69     copy_deps : bool, optional
  70         Copy javascript and CSS dependencies to output directory.
  71 
  72     Notes
  73     -----
  74     This function accepts extra parameters which will be forwarded to
  75     :class:`theano.d3viz.formatting.PyDotFormatter`.
  76 
  77     """
  78 
  79     # Create DOT graph
  80     formatter = PyDotFormatter(*args, **kwargs)
  81     graph = formatter(fct)
  82     dot_graph_raw = graph.create_dot()
  83     if not six.PY2:
  84         dot_graph_raw = dot_graph_raw.decode('utf8')
  85     dot_graph = escape_quotes(dot_graph_raw).replace('\n', '').replace('\r', '')
  86 
  87     # Create output directory if not existing
  88     outdir = os.path.dirname(outfile)
  89     if not outdir == '' and not os.path.exists(outdir):
  90         os.makedirs(outdir)
  91 
  92     # Read template HTML file
  93     template_file = os.path.join(__path__, 'html', 'template.html')
  94     with open(template_file) as f:
  95         template = f.read()
  96 
  97     # Copy dependencies to output directory
  98     src_deps = __path__
  99     if copy_deps:
  100         dst_deps = 'd3viz'
  101         for d in ['js', 'css']:
  102             dep = os.path.join(outdir, dst_deps, d)
  103             if not os.path.exists(dep):
  104                 shutil.copytree(os.path.join(src_deps, d), dep)
  105     else:
  106         dst_deps = src_deps
  107 
  108     # Replace patterns in template
  109     replace = {
  110         '%% JS_DIR %%': os.path.join(dst_deps, 'js'),
  111         '%% CSS_DIR %%': os.path.join(dst_deps, 'css'),
  112         '%% DOT_GRAPH %%': dot_graph,
  113     }
  114     html = replace_patterns(template, replace)
  115 
  116     # Write HTML file
  117     with open(outfile, 'w') as f:
  118         f.write(html)
  119 
  120 
  121 def d3write(fct, path, *args, **kwargs):
  122     """Convert Theano graph to pydot graph and write to dot file.
  123 
  124     Parameters
  125     ----------
  126     fct : theano.compile.function_module.Function
  127         A compiled Theano function, variable, apply or a list of variables.
  128     path: str
  129         Path to output file
  130 
  131     Notes
  132     -----
  133     This function accepts extra parameters which will be forwarded to
  134     :class:`theano.d3viz.formatting.PyDotFormatter`.
  135 
  136     """
  137 
  138     formatter = PyDotFormatter(*args, **kwargs)
  139     graph = formatter(fct)
  140     graph.write_dot(path)
  141
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/theano/d3viz/d3viz.py b/theano/d3viz/d3viz.py
  --- a/theano/d3viz/d3viz.py
  +++ b/theano/d3viz/d3viz.py
  @@ -5,8 +5,8 @@
   from __future__ import absolute_import, print_function, division
   
   import os
  +import json
   import shutil
  -import re
   import six
   from six import iteritems
   
  @@ -31,16 +31,15 @@
       return x
   
   
  -def escape_quotes(s):
  -    """Escape quotes in string.
  +def safe_json(obj):
  +    """Encode `obj` to JSON so that it can be embedded safely inside HTML.
   
       Parameters
       ----------
  -    s : str
  -        String on which function is applied
  +    obj : object
  +        object to serialize
       """
  -    s = re.sub(r'''(['"])''', r'\\\1', s)
  -    return s
  +    return json.dumps(obj).replace('<', '\\u003c')
   
   
   def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
  @@ -79,10 +78,9 @@
       # Create DOT graph
       formatter = PyDotFormatter(*args, **kwargs)
       graph = formatter(fct)
  -    dot_graph_raw = graph.create_dot()
  +    dot_graph = graph.create_dot()
       if not six.PY2:
  -        dot_graph_raw = dot_graph_raw.decode('utf8')
  -    dot_graph = escape_quotes(dot_graph_raw).replace('\n', '').replace('\r', '')
  +        dot_graph = dot_graph.decode('utf8')
   
       # Create output directory if not existing
       outdir = os.path.dirname(outfile)
  @@ -109,7 +107,7 @@
       replace = {
           '%% JS_DIR %%': os.path.join(dst_deps, 'js'),
           '%% CSS_DIR %%': os.path.join(dst_deps, 'css'),
  -        '%% DOT_GRAPH %%': dot_graph,
  +        '%% DOT_GRAPH %%': safe_json(dot_graph),
       }
       html = replace_patterns(template, replace)
  
verification_info: {"golden_diff": "diff --git a/theano/d3viz/d3viz.py b/theano/d3viz/d3viz.py\n--- a/theano/d3viz/d3viz.py\n+++ b/theano/d3viz/d3viz.py\n@@ -5,8 +5,8 @@\n from __future__ import absolute_import, print_function, division\n \n import os\n+import json\n import shutil\n-import re\n import six\n from six import iteritems\n \n@@ -31,16 +31,15 @@\n     return x\n \n \n-def escape_quotes(s):\n-    \"\"\"Escape quotes in string.\n+def safe_json(obj):\n+    \"\"\"Encode `obj` to JSON so that it can be embedded safely inside HTML.\n \n     Parameters\n     ----------\n-    s : str\n-        String on which function is applied\n+    obj : object\n+        object to serialize\n     \"\"\"\n-    s = re.sub(r'''(['\"])''', r'\\\\\\1', s)\n-    return s\n+    return json.dumps(obj).replace('<', '\\\\u003c')\n \n \n def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):\n@@ -79,10 +78,9 @@\n     # Create DOT graph\n     formatter = PyDotFormatter(*args, **kwargs)\n     graph = formatter(fct)\n-    dot_graph_raw = graph.create_dot()\n+    dot_graph = graph.create_dot()\n     if not six.PY2:\n-        dot_graph_raw = dot_graph_raw.decode('utf8')\n-    dot_graph = escape_quotes(dot_graph_raw).replace('\\n', '').replace('\\r', '')\n+        dot_graph = dot_graph.decode('utf8')\n \n     # Create output directory if not existing\n     outdir = os.path.dirname(outfile)\n@@ -109,7 +107,7 @@\n     replace = {\n         '%% JS_DIR %%': os.path.join(dst_deps, 'js'),\n         '%% CSS_DIR %%': os.path.join(dst_deps, 'css'),\n-        '%% DOT_GRAPH %%': dot_graph,\n+        '%% DOT_GRAPH %%': safe_json(dot_graph),\n     }\n     html = replace_patterns(template, replace)\n", "issue": "d3viz doesn't work for some graphs\nSometimes d3viz doesn't work for me - empty graph is displayed, and there is an error message in JS console. I tried to reduce it to a minimal example\n\n``` py\nimport os    \nos.environ['THEANO_FLAGS'] = \"device=gpu0,floatX=float32\" #,optimizer=fast_compile\"\n\nimport numpy as np\nfrom lasagne.updates import adam\nfrom theano import tensor as T, shared, function\nimport theano.d3viz as d3v\n\ndef show_d3(g):\n    d3v.d3viz(g, 'example.html')\n    from IPython.display import IFrame\n    return IFrame('example.html', width=800, height=500)\n\nx = T.fvector()\nW = shared(np.zeros((10, 5), dtype=np.float32))\nb = shared(np.zeros((10,), dtype=np.float32))\ny_true = T.fvector()\n\ny = T.nnet.sigmoid(T.dot(x, W) + b)\ncost = T.sqrt(((y - y_true)**2).sum())\n\nupdates = adam(cost, [W])  # no b!\nf_cost = function([x, y_true], cost, updates=updates)\nshow_d3(f_cost)\n```\n\n(IPython notebook: https://gist.github.com/kmike/13b0fb747dccd4f2f1e44789a9cb832c).\nThis is brittle: if `adam` is replaced with any other training method from Lasagne (or if a simple SGD is implemented manually) chart works; if `T.sqrt` is removed from `cost` expression chart works; if `T.nnet sigmoid` is removed from `y` expression chart works; if `b` is added to adam updates chart works; if `optimizer=fast_compile` is added to THEANO_FLAGS chart works.\n\n", "before_files": [{"content": "\"\"\"Dynamic visualization of Theano graphs.\n\nAuthor: Christof Angermueller <cangermueller@gmail.com>\n\"\"\"\nfrom __future__ import absolute_import, print_function, division\n\nimport os\nimport shutil\nimport re\nimport six\nfrom six import iteritems\n\nfrom theano.d3viz.formatting import PyDotFormatter\n\n__path__ = os.path.dirname(os.path.realpath(__file__))\n\n\ndef replace_patterns(x, replace):\n    \"\"\"Replace `replace` in string `x`.\n\n    Parameters\n    ----------\n    s : str\n        String on which function is applied\n    replace : dict\n        `key`, `value` pairs where key is a regular expression and `value` a\n        string by which `key` is replaced\n    \"\"\"\n    for from_, to in iteritems(replace):\n        x = x.replace(str(from_), str(to))\n    return x\n\n\ndef escape_quotes(s):\n    \"\"\"Escape quotes in string.\n\n    Parameters\n    ----------\n    s : str\n        String on which function is applied\n    \"\"\"\n    s = re.sub(r'''(['\"])''', r'\\\\\\1', s)\n    return s\n\n\ndef d3viz(fct, outfile, copy_deps=True, *args, **kwargs):\n    \"\"\"Create HTML file with dynamic visualizing of a Theano function graph.\n\n    In the HTML file, the whole graph or single nodes can be moved by drag and\n    drop. Zooming is possible via the mouse wheel. Detailed information about\n    nodes and edges are displayed via mouse-over events. Node labels can be\n    edited by selecting Edit from the context menu.\n\n    Input nodes are colored in green, output nodes in blue. Apply nodes are\n    ellipses, and colored depending on the type of operation they perform. Red\n    ellipses are transfers from/to the GPU (ops with names GpuFromHost,\n    HostFromGpu).\n\n    Edges are black by default. If a node returns a view of an\n    input, the input edge will be blue. If it returns a destroyed input, the\n    edge will be red.\n\n    Parameters\n    ----------\n    fct : theano.compile.function_module.Function\n        A compiled Theano function, variable, apply or a list of variables.\n    outfile : str\n        Path to output HTML file.\n    copy_deps : bool, optional\n        Copy javascript and CSS dependencies to output directory.\n\n    Notes\n    -----\n    This function accepts extra parameters which will be forwarded to\n    :class:`theano.d3viz.formatting.PyDotFormatter`.\n\n    \"\"\"\n\n    # Create DOT graph\n    formatter = PyDotFormatter(*args, **kwargs)\n    graph = formatter(fct)\n    dot_graph_raw = graph.create_dot()\n    if not six.PY2:\n        dot_graph_raw = dot_graph_raw.decode('utf8')\n    dot_graph = escape_quotes(dot_graph_raw).replace('\\n', '').replace('\\r', '')\n\n    # Create output directory if not existing\n    outdir = os.path.dirname(outfile)\n    if not outdir == '' and not os.path.exists(outdir):\n        os.makedirs(outdir)\n\n    # Read template HTML file\n    template_file = os.path.join(__path__, 'html', 'template.html')\n    with open(template_file) as f:\n        template = f.read()\n\n    # Copy dependencies to output directory\n    src_deps = __path__\n    if copy_deps:\n        dst_deps = 'd3viz'\n        for d in ['js', 'css']:\n            dep = os.path.join(outdir, dst_deps, d)\n            if not os.path.exists(dep):\n                shutil.copytree(os.path.join(src_deps, d), dep)\n    else:\n        dst_deps = src_deps\n\n    # Replace patterns in template\n    replace = {\n        '%% JS_DIR %%': os.path.join(dst_deps, 'js'),\n        '%% CSS_DIR %%': os.path.join(dst_deps, 'css'),\n        '%% DOT_GRAPH %%': dot_graph,\n    }\n    html = replace_patterns(template, replace)\n\n    # Write HTML file\n    with open(outfile, 'w') as f:\n        f.write(html)\n\n\ndef d3write(fct, path, *args, **kwargs):\n    \"\"\"Convert Theano graph to pydot graph and write to dot file.\n\n    Parameters\n    ----------\n    fct : theano.compile.function_module.Function\n        A compiled Theano function, variable, apply or a list of variables.\n    path: str\n        Path to output file\n\n    Notes\n    -----\n    This function accepts extra parameters which will be forwarded to\n    :class:`theano.d3viz.formatting.PyDotFormatter`.\n\n    \"\"\"\n\n    formatter = PyDotFormatter(*args, **kwargs)\n    graph = formatter(fct)\n    graph.write_dot(path)\n", "path": "theano/d3viz/d3viz.py"}], "after_files": [{"content": "\"\"\"Dynamic visualization of Theano graphs.\n\nAuthor: Christof Angermueller <cangermueller@gmail.com>\n\"\"\"\nfrom __future__ import absolute_import, print_function, division\n\nimport os\nimport json\nimport shutil\nimport six\nfrom six import iteritems\n\nfrom theano.d3viz.formatting import PyDotFormatter\n\n__path__ = os.path.dirname(os.path.realpath(__file__))\n\n\ndef replace_patterns(x, replace):\n    \"\"\"Replace `replace` in string `x`.\n\n    Parameters\n    ----------\n    s : str\n        String on which function is applied\n    replace : dict\n        `key`, `value` pairs where key is a regular expression and `value` a\n        string by which `key` is replaced\n    \"\"\"\n    for from_, to in iteritems(replace):\n        x = x.replace(str(from_), str(to))\n    return x\n\n\ndef safe_json(obj):\n    \"\"\"Encode `obj` to JSON so that it can be embedded safely inside HTML.\n\n    Parameters\n    ----------\n    obj : object\n        object to serialize\n    \"\"\"\n    return json.dumps(obj).replace('<', '\\\\u003c')\n\n\ndef d3viz(fct, outfile, copy_deps=True, *args, **kwargs):\n    \"\"\"Create HTML file with dynamic visualizing of a Theano function graph.\n\n    In the HTML file, the whole graph or single nodes can be moved by drag and\n    drop. Zooming is possible via the mouse wheel. Detailed information about\n    nodes and edges are displayed via mouse-over events. Node labels can be\n    edited by selecting Edit from the context menu.\n\n    Input nodes are colored in green, output nodes in blue. Apply nodes are\n    ellipses, and colored depending on the type of operation they perform. Red\n    ellipses are transfers from/to the GPU (ops with names GpuFromHost,\n    HostFromGpu).\n\n    Edges are black by default. If a node returns a view of an\n    input, the input edge will be blue. If it returns a destroyed input, the\n    edge will be red.\n\n    Parameters\n    ----------\n    fct : theano.compile.function_module.Function\n        A compiled Theano function, variable, apply or a list of variables.\n    outfile : str\n        Path to output HTML file.\n    copy_deps : bool, optional\n        Copy javascript and CSS dependencies to output directory.\n\n    Notes\n    -----\n    This function accepts extra parameters which will be forwarded to\n    :class:`theano.d3viz.formatting.PyDotFormatter`.\n\n    \"\"\"\n\n    # Create DOT graph\n    formatter = PyDotFormatter(*args, **kwargs)\n    graph = formatter(fct)\n    dot_graph = graph.create_dot()\n    if not six.PY2:\n        dot_graph = dot_graph.decode('utf8')\n\n    # Create output directory if not existing\n    outdir = os.path.dirname(outfile)\n    if not outdir == '' and not os.path.exists(outdir):\n        os.makedirs(outdir)\n\n    # Read template HTML file\n    template_file = os.path.join(__path__, 'html', 'template.html')\n    with open(template_file) as f:\n        template = f.read()\n\n    # Copy dependencies to output directory\n    src_deps = __path__\n    if copy_deps:\n        dst_deps = 'd3viz'\n        for d in ['js', 'css']:\n            dep = os.path.join(outdir, dst_deps, d)\n            if not os.path.exists(dep):\n                shutil.copytree(os.path.join(src_deps, d), dep)\n    else:\n        dst_deps = src_deps\n\n    # Replace patterns in template\n    replace = {\n        '%% JS_DIR %%': os.path.join(dst_deps, 'js'),\n        '%% CSS_DIR %%': os.path.join(dst_deps, 'css'),\n        '%% DOT_GRAPH %%': safe_json(dot_graph),\n    }\n    html = replace_patterns(template, replace)\n\n    # Write HTML file\n    with open(outfile, 'w') as f:\n        f.write(html)\n\n\ndef d3write(fct, path, *args, **kwargs):\n    \"\"\"Convert Theano graph to pydot graph and write to dot file.\n\n    Parameters\n    ----------\n    fct : theano.compile.function_module.Function\n        A compiled Theano function, variable, apply or a list of variables.\n    path: str\n        Path to output file\n\n    Notes\n    -----\n    This function accepts extra parameters which will be forwarded to\n    :class:`theano.d3viz.formatting.PyDotFormatter`.\n\n    \"\"\"\n\n    formatter = PyDotFormatter(*args, **kwargs)\n    graph = formatter(fct)\n    graph.write_dot(path)\n", "path": "theano/d3viz/d3viz.py"}]}