We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
displacy arc labels are place incorrectly in Jupyter notebook

| Software | Version |
|----------|---------|
| Python   | 3.6.4   |
| notebook | 5.4.1   |
| spacy    | 2.0.16  |

The SVG contents is the same when I copy the HTML from the inspector both in
jupyter and from the `displacy.serve` webpage.

When viewed through `displacy.serve`:

![displacy-serve](https://user-images.githubusercontent.com/966205/48501958-58c53f80-e836-11e8-9a11-af5de1d67a41.png)

And in Jupyter:
![displacy jupyter](https://user-images.githubusercontent.com/966205/48501957-58c53f80-e836-11e8-81f9-87f97eed32b8.png)

The SVG generated is the same, so I suspect some CSS issue is overriding the default, I don't know whether that should be solved within Jupyter, or whether it's spaCy's responsibility to make portable SVGs.  

Generated SVG here: https://gist.github.com/willprice/66d9ff961b693abe19e94d541eaacb99

This happens both in Firefox and Chrome.

I had a poke twiddling CSS rules off and on but couldn't seem to find any rules that affected the placement. Let me know if there's anything I can do providing additional info to help resolve the issue.

Thanks for the awesome library!

displacy arc labels are place incorrectly in Jupyter notebook

| Software | Version |
|----------|---------|
| Python   | 3.6.4   |
| notebook | 5.4.1   |
| spacy    | 2.0.16  |

The SVG contents is the same when I copy the HTML from the inspector both in
jupyter and from the `displacy.serve` webpage.

When viewed through `displacy.serve`:

![displacy-serve](https://user-images.githubusercontent.com/966205/48501958-58c53f80-e836-11e8-9a11-af5de1d67a41.png)

And in Jupyter:
![displacy jupyter](https://user-images.githubusercontent.com/966205/48501957-58c53f80-e836-11e8-81f9-87f97eed32b8.png)

The SVG generated is the same, so I suspect some CSS issue is overriding the default, I don't know whether that should be solved within Jupyter, or whether it's spaCy's responsibility to make portable SVGs.  

Generated SVG here: https://gist.github.com/willprice/66d9ff961b693abe19e94d541eaacb99

This happens both in Firefox and Chrome.

I had a poke twiddling CSS rules off and on but couldn't seem to find any rules that affected the placement. Let me know if there's anything I can do providing additional info to help resolve the issue.

Thanks for the awesome library!


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `spacy/displacy/render.py`
Content:
```
1 # coding: utf8
2 from __future__ import unicode_literals
3 
4 from .templates import TPL_DEP_SVG, TPL_DEP_WORDS, TPL_DEP_ARCS
5 from .templates import TPL_ENT, TPL_ENTS, TPL_FIGURE, TPL_TITLE, TPL_PAGE
6 from ..util import minify_html, escape_html
7 
8 
9 class DependencyRenderer(object):
10     """Render dependency parses as SVGs."""
11     style = 'dep'
12 
13     def __init__(self, options={}):
14         """Initialise dependency renderer.
15 
16         options (dict): Visualiser-specific options (compact, word_spacing,
17             arrow_spacing, arrow_width, arrow_stroke, distance, offset_x,
18             color, bg, font)
19         """
20         self.compact = options.get('compact', False)
21         self.word_spacing = options.get('word_spacing', 45)
22         self.arrow_spacing = options.get('arrow_spacing',
23                                          12 if self.compact else 20)
24         self.arrow_width = options.get('arrow_width',
25                                        6 if self.compact else 10)
26         self.arrow_stroke = options.get('arrow_stroke', 2)
27         self.distance = options.get('distance', 150 if self.compact else 175)
28         self.offset_x = options.get('offset_x', 50)
29         self.color = options.get('color', '#000000')
30         self.bg = options.get('bg', '#ffffff')
31         self.font = options.get('font', 'Arial')
32 
33     def render(self, parsed, page=False, minify=False):
34         """Render complete markup.
35 
36         parsed (list): Dependency parses to render.
37         page (bool): Render parses wrapped as full HTML page.
38         minify (bool): Minify HTML markup.
39         RETURNS (unicode): Rendered SVG or HTML markup.
40         """
41         rendered = [self.render_svg(i, p['words'], p['arcs'])
42                     for i, p in enumerate(parsed)]
43         if page:
44             content = ''.join([TPL_FIGURE.format(content=svg)
45                                for svg in rendered])
46             markup = TPL_PAGE.format(content=content)
47         else:
48             markup = ''.join(rendered)
49         if minify:
50             return minify_html(markup)
51         return markup
52 
53     def render_svg(self, render_id, words, arcs):
54         """Render SVG.
55 
56         render_id (int): Unique ID, typically index of document.
57         words (list): Individual words and their tags.
58         arcs (list): Individual arcs and their start, end, direction and label.
59         RETURNS (unicode): Rendered SVG markup.
60         """
61         self.levels = self.get_levels(arcs)
62         self.highest_level = len(self.levels)
63         self.offset_y = self.distance/2*self.highest_level+self.arrow_stroke
64         self.width = self.offset_x+len(words)*self.distance
65         self.height = self.offset_y+3*self.word_spacing
66         self.id = render_id
67         words = [self.render_word(w['text'], w['tag'], i)
68                  for i, w in enumerate(words)]
69         arcs = [self.render_arrow(a['label'], a['start'],
70                                   a['end'], a['dir'], i)
71                 for i, a in enumerate(arcs)]
72         content = ''.join(words) + ''.join(arcs)
73         return TPL_DEP_SVG.format(id=self.id, width=self.width,
74                                   height=self.height, color=self.color,
75                                   bg=self.bg, font=self.font, content=content)
76 
77     def render_word(self, text, tag, i):
78         """Render individual word.
79 
80         text (unicode): Word text.
81         tag (unicode): Part-of-speech tag.
82         i (int): Unique ID, typically word index.
83         RETURNS (unicode): Rendered SVG markup.
84         """
85         y = self.offset_y+self.word_spacing
86         x = self.offset_x+i*self.distance
87         html_text = escape_html(text)
88         return TPL_DEP_WORDS.format(text=html_text, tag=tag, x=x, y=y)
89 
90 
91     def render_arrow(self, label, start, end, direction, i):
92         """Render indivicual arrow.
93 
94         label (unicode): Dependency label.
95         start (int): Index of start word.
96         end (int): Index of end word.
97         direction (unicode): Arrow direction, 'left' or 'right'.
98         i (int): Unique ID, typically arrow index.
99         RETURNS (unicode): Rendered SVG markup.
100         """
101         level = self.levels.index(end-start)+1
102         x_start = self.offset_x+start*self.distance+self.arrow_spacing
103         y = self.offset_y
104         x_end = (self.offset_x+(end-start)*self.distance+start*self.distance
105                  - self.arrow_spacing*(self.highest_level-level)/4)
106         y_curve = self.offset_y-level*self.distance/2
107         if self.compact:
108             y_curve = self.offset_y-level*self.distance/6
109         if y_curve == 0 and len(self.levels) > 5:
110             y_curve = -self.distance
111         arrowhead = self.get_arrowhead(direction, x_start, y, x_end)
112         arc = self.get_arc(x_start, y, y_curve, x_end)
113         return TPL_DEP_ARCS.format(id=self.id, i=i, stroke=self.arrow_stroke,
114                                    head=arrowhead, label=label, arc=arc)
115 
116     def get_arc(self, x_start, y, y_curve, x_end):
117         """Render individual arc.
118 
119         x_start (int): X-coordinate of arrow start point.
120         y (int): Y-coordinate of arrow start and end point.
121         y_curve (int): Y-corrdinate of Cubic Bézier y_curve point.
122         x_end (int): X-coordinate of arrow end point.
123         RETURNS (unicode): Definition of the arc path ('d' attribute).
124         """
125         template = "M{x},{y} C{x},{c} {e},{c} {e},{y}"
126         if self.compact:
127             template = "M{x},{y} {x},{c} {e},{c} {e},{y}"
128         return template.format(x=x_start, y=y, c=y_curve, e=x_end)
129 
130     def get_arrowhead(self, direction, x, y, end):
131         """Render individual arrow head.
132 
133         direction (unicode): Arrow direction, 'left' or 'right'.
134         x (int): X-coordinate of arrow start point.
135         y (int): Y-coordinate of arrow start and end point.
136         end (int): X-coordinate of arrow end point.
137         RETURNS (unicode): Definition of the arrow head path ('d' attribute).
138         """
139         if direction == 'left':
140             pos1, pos2, pos3 = (x, x-self.arrow_width+2, x+self.arrow_width-2)
141         else:
142             pos1, pos2, pos3 = (end, end+self.arrow_width-2,
143                                 end-self.arrow_width+2)
144         arrowhead = (pos1, y+2, pos2, y-self.arrow_width, pos3,
145                      y-self.arrow_width)
146         return "M{},{} L{},{} {},{}".format(*arrowhead)
147 
148     def get_levels(self, arcs):
149         """Calculate available arc height "levels".
150         Used to calculate arrow heights dynamically and without wasting space.
151 
152         args (list): Individual arcs and their start, end, direction and label.
153         RETURNS (list): Arc levels sorted from lowest to highest.
154         """
155         levels = set(map(lambda arc: arc['end'] - arc['start'], arcs))
156         return sorted(list(levels))
157 
158 
159 class EntityRenderer(object):
160     """Render named entities as HTML."""
161     style = 'ent'
162 
163     def __init__(self, options={}):
164         """Initialise dependency renderer.
165 
166         options (dict): Visualiser-specific options (colors, ents)
167         """
168         colors = {'ORG': '#7aecec', 'PRODUCT': '#bfeeb7', 'GPE': '#feca74',
169                   'LOC': '#ff9561', 'PERSON': '#aa9cfc', 'NORP': '#c887fb',
170                   'FACILITY': '#9cc9cc', 'EVENT': '#ffeb80', 'LAW': '#ff8197',
171                   'LANGUAGE': '#ff8197', 'WORK_OF_ART': '#f0d0ff',
172                   'DATE': '#bfe1d9', 'TIME': '#bfe1d9', 'MONEY': '#e4e7d2',
173                   'QUANTITY': '#e4e7d2', 'ORDINAL': '#e4e7d2',
174                   'CARDINAL': '#e4e7d2', 'PERCENT': '#e4e7d2'}
175         colors.update(options.get('colors', {}))
176         self.default_color = '#ddd'
177         self.colors = colors
178         self.ents = options.get('ents', None)
179 
180     def render(self, parsed, page=False, minify=False):
181         """Render complete markup.
182 
183         parsed (list): Dependency parses to render.
184         page (bool): Render parses wrapped as full HTML page.
185         minify (bool): Minify HTML markup.
186         RETURNS (unicode): Rendered HTML markup.
187         """
188         rendered = [self.render_ents(p['text'], p['ents'],
189                     p.get('title', None)) for p in parsed]
190         if page:
191             docs = ''.join([TPL_FIGURE.format(content=doc)
192                             for doc in rendered])
193             markup = TPL_PAGE.format(content=docs)
194         else:
195             markup = ''.join(rendered)
196         if minify:
197             return minify_html(markup)
198         return markup
199 
200     def render_ents(self, text, spans, title):
201         """Render entities in text.
202 
203         text (unicode): Original text.
204         spans (list): Individual entity spans and their start, end and label.
205         title (unicode or None): Document title set in Doc.user_data['title'].
206         """
207         markup = ''
208         offset = 0
209         for span in spans:
210             label = span['label']
211             start = span['start']
212             end = span['end']
213             entity = text[start:end]
214             fragments = text[offset:start].split('\n')
215             for i, fragment in enumerate(fragments):
216                 markup += fragment
217                 if len(fragments) > 1 and i != len(fragments)-1:
218                     markup += '</br>'
219             if self.ents is None or label.upper() in self.ents:
220                 color = self.colors.get(label.upper(), self.default_color)
221                 markup += TPL_ENT.format(label=label, text=entity, bg=color)
222             else:
223                 markup += entity
224             offset = end
225         markup += text[offset:]
226         markup = TPL_ENTS.format(content=markup, colors=self.colors)
227         if title:
228             markup = TPL_TITLE.format(title=title) + markup
229         return markup
230
```
--- 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()

```

diff --git a/spacy/displacy/render.py b/spacy/displacy/render.py
--- a/spacy/displacy/render.py
+++ b/spacy/displacy/render.py
@@ -1,6 +1,8 @@
 # coding: utf8
 from __future__ import unicode_literals
 
+import random
+
 from .templates import TPL_DEP_SVG, TPL_DEP_WORDS, TPL_DEP_ARCS
 from .templates import TPL_ENT, TPL_ENTS, TPL_FIGURE, TPL_TITLE, TPL_PAGE
 from ..util import minify_html, escape_html
@@ -38,7 +40,10 @@
         minify (bool): Minify HTML markup.
         RETURNS (unicode): Rendered SVG or HTML markup.
         """
-        rendered = [self.render_svg(i, p['words'], p['arcs'])
+        # Create a random ID prefix to make sure parses don't receive the
+        # same ID, even if they're identical
+        id_prefix = random.randint(0, 999)
+        rendered = [self.render_svg('{}-{}'.format(id_prefix, i), p['words'], p['arcs'])
                     for i, p in enumerate(parsed)]
         if page:
             content = ''.join([TPL_FIGURE.format(content=svg)

{"golden_diff": "diff --git a/spacy/displacy/render.py b/spacy/displacy/render.py\n--- a/spacy/displacy/render.py\n+++ b/spacy/displacy/render.py\n@@ -1,6 +1,8 @@\n # coding: utf8\n from __future__ import unicode_literals\n \n+import random\n+\n from .templates import TPL_DEP_SVG, TPL_DEP_WORDS, TPL_DEP_ARCS\n from .templates import TPL_ENT, TPL_ENTS, TPL_FIGURE, TPL_TITLE, TPL_PAGE\n from ..util import minify_html, escape_html\n@@ -38,7 +40,10 @@\n         minify (bool): Minify HTML markup.\n         RETURNS (unicode): Rendered SVG or HTML markup.\n         \"\"\"\n-        rendered = [self.render_svg(i, p['words'], p['arcs'])\n+        # Create a random ID prefix to make sure parses don't receive the\n+        # same ID, even if they're identical\n+        id_prefix = random.randint(0, 999)\n+        rendered = [self.render_svg('{}-{}'.format(id_prefix, i), p['words'], p['arcs'])\n                     for i, p in enumerate(parsed)]\n         if page:\n             content = ''.join([TPL_FIGURE.format(content=svg)\n", "issue": "displacy arc labels are place incorrectly in Jupyter notebook\n\r\n| Software | Version |\r\n|----------|---------|\r\n| Python   | 3.6.4   |\r\n| notebook | 5.4.1   |\r\n| spacy    | 2.0.16  |\r\n\r\nThe SVG contents is the same when I copy the HTML from the inspector both in\r\njupyter and from the `displacy.serve` webpage.\r\n\r\nWhen viewed through `displacy.serve`:\r\n\r\n![displacy-serve](https://user-images.githubusercontent.com/966205/48501958-58c53f80-e836-11e8-9a11-af5de1d67a41.png)\r\n\r\nAnd in Jupyter:\r\n![displacy jupyter](https://user-images.githubusercontent.com/966205/48501957-58c53f80-e836-11e8-81f9-87f97eed32b8.png)\r\n\r\nThe SVG generated is the same, so I suspect some CSS issue is overriding the default, I don't know whether that should be solved within Jupyter, or whether it's spaCy's responsibility to make portable SVGs.  \r\n\r\nGenerated SVG here: https://gist.github.com/willprice/66d9ff961b693abe19e94d541eaacb99\r\n\r\nThis happens both in Firefox and Chrome.\r\n\r\nI had a poke twiddling CSS rules off and on but couldn't seem to find any rules that affected the placement. Let me know if there's anything I can do providing additional info to help resolve the issue.\r\n\r\nThanks for the awesome library!\r\n\ndisplacy arc labels are place incorrectly in Jupyter notebook\n\r\n| Software | Version |\r\n|----------|---------|\r\n| Python   | 3.6.4   |\r\n| notebook | 5.4.1   |\r\n| spacy    | 2.0.16  |\r\n\r\nThe SVG contents is the same when I copy the HTML from the inspector both in\r\njupyter and from the `displacy.serve` webpage.\r\n\r\nWhen viewed through `displacy.serve`:\r\n\r\n![displacy-serve](https://user-images.githubusercontent.com/966205/48501958-58c53f80-e836-11e8-9a11-af5de1d67a41.png)\r\n\r\nAnd in Jupyter:\r\n![displacy jupyter](https://user-images.githubusercontent.com/966205/48501957-58c53f80-e836-11e8-81f9-87f97eed32b8.png)\r\n\r\nThe SVG generated is the same, so I suspect some CSS issue is overriding the default, I don't know whether that should be solved within Jupyter, or whether it's spaCy's responsibility to make portable SVGs.  \r\n\r\nGenerated SVG here: https://gist.github.com/willprice/66d9ff961b693abe19e94d541eaacb99\r\n\r\nThis happens both in Firefox and Chrome.\r\n\r\nI had a poke twiddling CSS rules off and on but couldn't seem to find any rules that affected the placement. Let me know if there's anything I can do providing additional info to help resolve the issue.\r\n\r\nThanks for the awesome library!\r\n\n", "before_files": [{"content": "# coding: utf8\nfrom __future__ import unicode_literals\n\nfrom .templates import TPL_DEP_SVG, TPL_DEP_WORDS, TPL_DEP_ARCS\nfrom .templates import TPL_ENT, TPL_ENTS, TPL_FIGURE, TPL_TITLE, TPL_PAGE\nfrom ..util import minify_html, escape_html\n\n\nclass DependencyRenderer(object):\n    \"\"\"Render dependency parses as SVGs.\"\"\"\n    style = 'dep'\n\n    def __init__(self, options={}):\n        \"\"\"Initialise dependency renderer.\n\n        options (dict): Visualiser-specific options (compact, word_spacing,\n            arrow_spacing, arrow_width, arrow_stroke, distance, offset_x,\n            color, bg, font)\n        \"\"\"\n        self.compact = options.get('compact', False)\n        self.word_spacing = options.get('word_spacing', 45)\n        self.arrow_spacing = options.get('arrow_spacing',\n                                         12 if self.compact else 20)\n        self.arrow_width = options.get('arrow_width',\n                                       6 if self.compact else 10)\n        self.arrow_stroke = options.get('arrow_stroke', 2)\n        self.distance = options.get('distance', 150 if self.compact else 175)\n        self.offset_x = options.get('offset_x', 50)\n        self.color = options.get('color', '#000000')\n        self.bg = options.get('bg', '#ffffff')\n        self.font = options.get('font', 'Arial')\n\n    def render(self, parsed, page=False, minify=False):\n        \"\"\"Render complete markup.\n\n        parsed (list): Dependency parses to render.\n        page (bool): Render parses wrapped as full HTML page.\n        minify (bool): Minify HTML markup.\n        RETURNS (unicode): Rendered SVG or HTML markup.\n        \"\"\"\n        rendered = [self.render_svg(i, p['words'], p['arcs'])\n                    for i, p in enumerate(parsed)]\n        if page:\n            content = ''.join([TPL_FIGURE.format(content=svg)\n                               for svg in rendered])\n            markup = TPL_PAGE.format(content=content)\n        else:\n            markup = ''.join(rendered)\n        if minify:\n            return minify_html(markup)\n        return markup\n\n    def render_svg(self, render_id, words, arcs):\n        \"\"\"Render SVG.\n\n        render_id (int): Unique ID, typically index of document.\n        words (list): Individual words and their tags.\n        arcs (list): Individual arcs and their start, end, direction and label.\n        RETURNS (unicode): Rendered SVG markup.\n        \"\"\"\n        self.levels = self.get_levels(arcs)\n        self.highest_level = len(self.levels)\n        self.offset_y = self.distance/2*self.highest_level+self.arrow_stroke\n        self.width = self.offset_x+len(words)*self.distance\n        self.height = self.offset_y+3*self.word_spacing\n        self.id = render_id\n        words = [self.render_word(w['text'], w['tag'], i)\n                 for i, w in enumerate(words)]\n        arcs = [self.render_arrow(a['label'], a['start'],\n                                  a['end'], a['dir'], i)\n                for i, a in enumerate(arcs)]\n        content = ''.join(words) + ''.join(arcs)\n        return TPL_DEP_SVG.format(id=self.id, width=self.width,\n                                  height=self.height, color=self.color,\n                                  bg=self.bg, font=self.font, content=content)\n\n    def render_word(self, text, tag, i):\n        \"\"\"Render individual word.\n\n        text (unicode): Word text.\n        tag (unicode): Part-of-speech tag.\n        i (int): Unique ID, typically word index.\n        RETURNS (unicode): Rendered SVG markup.\n        \"\"\"\n        y = self.offset_y+self.word_spacing\n        x = self.offset_x+i*self.distance\n        html_text = escape_html(text)\n        return TPL_DEP_WORDS.format(text=html_text, tag=tag, x=x, y=y)\n\n\n    def render_arrow(self, label, start, end, direction, i):\n        \"\"\"Render indivicual arrow.\n\n        label (unicode): Dependency label.\n        start (int): Index of start word.\n        end (int): Index of end word.\n        direction (unicode): Arrow direction, 'left' or 'right'.\n        i (int): Unique ID, typically arrow index.\n        RETURNS (unicode): Rendered SVG markup.\n        \"\"\"\n        level = self.levels.index(end-start)+1\n        x_start = self.offset_x+start*self.distance+self.arrow_spacing\n        y = self.offset_y\n        x_end = (self.offset_x+(end-start)*self.distance+start*self.distance\n                 - self.arrow_spacing*(self.highest_level-level)/4)\n        y_curve = self.offset_y-level*self.distance/2\n        if self.compact:\n            y_curve = self.offset_y-level*self.distance/6\n        if y_curve == 0 and len(self.levels) > 5:\n            y_curve = -self.distance\n        arrowhead = self.get_arrowhead(direction, x_start, y, x_end)\n        arc = self.get_arc(x_start, y, y_curve, x_end)\n        return TPL_DEP_ARCS.format(id=self.id, i=i, stroke=self.arrow_stroke,\n                                   head=arrowhead, label=label, arc=arc)\n\n    def get_arc(self, x_start, y, y_curve, x_end):\n        \"\"\"Render individual arc.\n\n        x_start (int): X-coordinate of arrow start point.\n        y (int): Y-coordinate of arrow start and end point.\n        y_curve (int): Y-corrdinate of Cubic B\u00e9zier y_curve point.\n        x_end (int): X-coordinate of arrow end point.\n        RETURNS (unicode): Definition of the arc path ('d' attribute).\n        \"\"\"\n        template = \"M{x},{y} C{x},{c} {e},{c} {e},{y}\"\n        if self.compact:\n            template = \"M{x},{y} {x},{c} {e},{c} {e},{y}\"\n        return template.format(x=x_start, y=y, c=y_curve, e=x_end)\n\n    def get_arrowhead(self, direction, x, y, end):\n        \"\"\"Render individual arrow head.\n\n        direction (unicode): Arrow direction, 'left' or 'right'.\n        x (int): X-coordinate of arrow start point.\n        y (int): Y-coordinate of arrow start and end point.\n        end (int): X-coordinate of arrow end point.\n        RETURNS (unicode): Definition of the arrow head path ('d' attribute).\n        \"\"\"\n        if direction == 'left':\n            pos1, pos2, pos3 = (x, x-self.arrow_width+2, x+self.arrow_width-2)\n        else:\n            pos1, pos2, pos3 = (end, end+self.arrow_width-2,\n                                end-self.arrow_width+2)\n        arrowhead = (pos1, y+2, pos2, y-self.arrow_width, pos3,\n                     y-self.arrow_width)\n        return \"M{},{} L{},{} {},{}\".format(*arrowhead)\n\n    def get_levels(self, arcs):\n        \"\"\"Calculate available arc height \"levels\".\n        Used to calculate arrow heights dynamically and without wasting space.\n\n        args (list): Individual arcs and their start, end, direction and label.\n        RETURNS (list): Arc levels sorted from lowest to highest.\n        \"\"\"\n        levels = set(map(lambda arc: arc['end'] - arc['start'], arcs))\n        return sorted(list(levels))\n\n\nclass EntityRenderer(object):\n    \"\"\"Render named entities as HTML.\"\"\"\n    style = 'ent'\n\n    def __init__(self, options={}):\n        \"\"\"Initialise dependency renderer.\n\n        options (dict): Visualiser-specific options (colors, ents)\n        \"\"\"\n        colors = {'ORG': '#7aecec', 'PRODUCT': '#bfeeb7', 'GPE': '#feca74',\n                  'LOC': '#ff9561', 'PERSON': '#aa9cfc', 'NORP': '#c887fb',\n                  'FACILITY': '#9cc9cc', 'EVENT': '#ffeb80', 'LAW': '#ff8197',\n                  'LANGUAGE': '#ff8197', 'WORK_OF_ART': '#f0d0ff',\n                  'DATE': '#bfe1d9', 'TIME': '#bfe1d9', 'MONEY': '#e4e7d2',\n                  'QUANTITY': '#e4e7d2', 'ORDINAL': '#e4e7d2',\n                  'CARDINAL': '#e4e7d2', 'PERCENT': '#e4e7d2'}\n        colors.update(options.get('colors', {}))\n        self.default_color = '#ddd'\n        self.colors = colors\n        self.ents = options.get('ents', None)\n\n    def render(self, parsed, page=False, minify=False):\n        \"\"\"Render complete markup.\n\n        parsed (list): Dependency parses to render.\n        page (bool): Render parses wrapped as full HTML page.\n        minify (bool): Minify HTML markup.\n        RETURNS (unicode): Rendered HTML markup.\n        \"\"\"\n        rendered = [self.render_ents(p['text'], p['ents'],\n                    p.get('title', None)) for p in parsed]\n        if page:\n            docs = ''.join([TPL_FIGURE.format(content=doc)\n                            for doc in rendered])\n            markup = TPL_PAGE.format(content=docs)\n        else:\n            markup = ''.join(rendered)\n        if minify:\n            return minify_html(markup)\n        return markup\n\n    def render_ents(self, text, spans, title):\n        \"\"\"Render entities in text.\n\n        text (unicode): Original text.\n        spans (list): Individual entity spans and their start, end and label.\n        title (unicode or None): Document title set in Doc.user_data['title'].\n        \"\"\"\n        markup = ''\n        offset = 0\n        for span in spans:\n            label = span['label']\n            start = span['start']\n            end = span['end']\n            entity = text[start:end]\n            fragments = text[offset:start].split('\\n')\n            for i, fragment in enumerate(fragments):\n                markup += fragment\n                if len(fragments) > 1 and i != len(fragments)-1:\n                    markup += '</br>'\n            if self.ents is None or label.upper() in self.ents:\n                color = self.colors.get(label.upper(), self.default_color)\n                markup += TPL_ENT.format(label=label, text=entity, bg=color)\n            else:\n                markup += entity\n            offset = end\n        markup += text[offset:]\n        markup = TPL_ENTS.format(content=markup, colors=self.colors)\n        if title:\n            markup = TPL_TITLE.format(title=title) + markup\n        return markup\n", "path": "spacy/displacy/render.py"}], "after_files": [{"content": "# coding: utf8\nfrom __future__ import unicode_literals\n\nimport random\n\nfrom .templates import TPL_DEP_SVG, TPL_DEP_WORDS, TPL_DEP_ARCS\nfrom .templates import TPL_ENT, TPL_ENTS, TPL_FIGURE, TPL_TITLE, TPL_PAGE\nfrom ..util import minify_html, escape_html\n\n\nclass DependencyRenderer(object):\n    \"\"\"Render dependency parses as SVGs.\"\"\"\n    style = 'dep'\n\n    def __init__(self, options={}):\n        \"\"\"Initialise dependency renderer.\n\n        options (dict): Visualiser-specific options (compact, word_spacing,\n            arrow_spacing, arrow_width, arrow_stroke, distance, offset_x,\n            color, bg, font)\n        \"\"\"\n        self.compact = options.get('compact', False)\n        self.word_spacing = options.get('word_spacing', 45)\n        self.arrow_spacing = options.get('arrow_spacing',\n                                         12 if self.compact else 20)\n        self.arrow_width = options.get('arrow_width',\n                                       6 if self.compact else 10)\n        self.arrow_stroke = options.get('arrow_stroke', 2)\n        self.distance = options.get('distance', 150 if self.compact else 175)\n        self.offset_x = options.get('offset_x', 50)\n        self.color = options.get('color', '#000000')\n        self.bg = options.get('bg', '#ffffff')\n        self.font = options.get('font', 'Arial')\n\n    def render(self, parsed, page=False, minify=False):\n        \"\"\"Render complete markup.\n\n        parsed (list): Dependency parses to render.\n        page (bool): Render parses wrapped as full HTML page.\n        minify (bool): Minify HTML markup.\n        RETURNS (unicode): Rendered SVG or HTML markup.\n        \"\"\"\n        # Create a random ID prefix to make sure parses don't receive the\n        # same ID, even if they're identical\n        id_prefix = random.randint(0, 999)\n        rendered = [self.render_svg('{}-{}'.format(id_prefix, i), p['words'], p['arcs'])\n                    for i, p in enumerate(parsed)]\n        if page:\n            content = ''.join([TPL_FIGURE.format(content=svg)\n                               for svg in rendered])\n            markup = TPL_PAGE.format(content=content)\n        else:\n            markup = ''.join(rendered)\n        if minify:\n            return minify_html(markup)\n        return markup\n\n    def render_svg(self, render_id, words, arcs):\n        \"\"\"Render SVG.\n\n        render_id (int): Unique ID, typically index of document.\n        words (list): Individual words and their tags.\n        arcs (list): Individual arcs and their start, end, direction and label.\n        RETURNS (unicode): Rendered SVG markup.\n        \"\"\"\n        self.levels = self.get_levels(arcs)\n        self.highest_level = len(self.levels)\n        self.offset_y = self.distance/2*self.highest_level+self.arrow_stroke\n        self.width = self.offset_x+len(words)*self.distance\n        self.height = self.offset_y+3*self.word_spacing\n        self.id = render_id\n        words = [self.render_word(w['text'], w['tag'], i)\n                 for i, w in enumerate(words)]\n        arcs = [self.render_arrow(a['label'], a['start'],\n                                  a['end'], a['dir'], i)\n                for i, a in enumerate(arcs)]\n        content = ''.join(words) + ''.join(arcs)\n        return TPL_DEP_SVG.format(id=self.id, width=self.width,\n                                  height=self.height, color=self.color,\n                                  bg=self.bg, font=self.font, content=content)\n\n    def render_word(self, text, tag, i):\n        \"\"\"Render individual word.\n\n        text (unicode): Word text.\n        tag (unicode): Part-of-speech tag.\n        i (int): Unique ID, typically word index.\n        RETURNS (unicode): Rendered SVG markup.\n        \"\"\"\n        y = self.offset_y+self.word_spacing\n        x = self.offset_x+i*self.distance\n        html_text = escape_html(text)\n        return TPL_DEP_WORDS.format(text=html_text, tag=tag, x=x, y=y)\n\n\n    def render_arrow(self, label, start, end, direction, i):\n        \"\"\"Render indivicual arrow.\n\n        label (unicode): Dependency label.\n        start (int): Index of start word.\n        end (int): Index of end word.\n        direction (unicode): Arrow direction, 'left' or 'right'.\n        i (int): Unique ID, typically arrow index.\n        RETURNS (unicode): Rendered SVG markup.\n        \"\"\"\n        level = self.levels.index(end-start)+1\n        x_start = self.offset_x+start*self.distance+self.arrow_spacing\n        y = self.offset_y\n        x_end = (self.offset_x+(end-start)*self.distance+start*self.distance\n                 - self.arrow_spacing*(self.highest_level-level)/4)\n        y_curve = self.offset_y-level*self.distance/2\n        if self.compact:\n            y_curve = self.offset_y-level*self.distance/6\n        if y_curve == 0 and len(self.levels) > 5:\n            y_curve = -self.distance\n        arrowhead = self.get_arrowhead(direction, x_start, y, x_end)\n        arc = self.get_arc(x_start, y, y_curve, x_end)\n        return TPL_DEP_ARCS.format(id=self.id, i=i, stroke=self.arrow_stroke,\n                                   head=arrowhead, label=label, arc=arc)\n\n    def get_arc(self, x_start, y, y_curve, x_end):\n        \"\"\"Render individual arc.\n\n        x_start (int): X-coordinate of arrow start point.\n        y (int): Y-coordinate of arrow start and end point.\n        y_curve (int): Y-corrdinate of Cubic B\u00e9zier y_curve point.\n        x_end (int): X-coordinate of arrow end point.\n        RETURNS (unicode): Definition of the arc path ('d' attribute).\n        \"\"\"\n        template = \"M{x},{y} C{x},{c} {e},{c} {e},{y}\"\n        if self.compact:\n            template = \"M{x},{y} {x},{c} {e},{c} {e},{y}\"\n        return template.format(x=x_start, y=y, c=y_curve, e=x_end)\n\n    def get_arrowhead(self, direction, x, y, end):\n        \"\"\"Render individual arrow head.\n\n        direction (unicode): Arrow direction, 'left' or 'right'.\n        x (int): X-coordinate of arrow start point.\n        y (int): Y-coordinate of arrow start and end point.\n        end (int): X-coordinate of arrow end point.\n        RETURNS (unicode): Definition of the arrow head path ('d' attribute).\n        \"\"\"\n        if direction == 'left':\n            pos1, pos2, pos3 = (x, x-self.arrow_width+2, x+self.arrow_width-2)\n        else:\n            pos1, pos2, pos3 = (end, end+self.arrow_width-2,\n                                end-self.arrow_width+2)\n        arrowhead = (pos1, y+2, pos2, y-self.arrow_width, pos3,\n                     y-self.arrow_width)\n        return \"M{},{} L{},{} {},{}\".format(*arrowhead)\n\n    def get_levels(self, arcs):\n        \"\"\"Calculate available arc height \"levels\".\n        Used to calculate arrow heights dynamically and without wasting space.\n\n        args (list): Individual arcs and their start, end, direction and label.\n        RETURNS (list): Arc levels sorted from lowest to highest.\n        \"\"\"\n        levels = set(map(lambda arc: arc['end'] - arc['start'], arcs))\n        return sorted(list(levels))\n\n\nclass EntityRenderer(object):\n    \"\"\"Render named entities as HTML.\"\"\"\n    style = 'ent'\n\n    def __init__(self, options={}):\n        \"\"\"Initialise dependency renderer.\n\n        options (dict): Visualiser-specific options (colors, ents)\n        \"\"\"\n        colors = {'ORG': '#7aecec', 'PRODUCT': '#bfeeb7', 'GPE': '#feca74',\n                  'LOC': '#ff9561', 'PERSON': '#aa9cfc', 'NORP': '#c887fb',\n                  'FACILITY': '#9cc9cc', 'EVENT': '#ffeb80', 'LAW': '#ff8197',\n                  'LANGUAGE': '#ff8197', 'WORK_OF_ART': '#f0d0ff',\n                  'DATE': '#bfe1d9', 'TIME': '#bfe1d9', 'MONEY': '#e4e7d2',\n                  'QUANTITY': '#e4e7d2', 'ORDINAL': '#e4e7d2',\n                  'CARDINAL': '#e4e7d2', 'PERCENT': '#e4e7d2'}\n        colors.update(options.get('colors', {}))\n        self.default_color = '#ddd'\n        self.colors = colors\n        self.ents = options.get('ents', None)\n\n    def render(self, parsed, page=False, minify=False):\n        \"\"\"Render complete markup.\n\n        parsed (list): Dependency parses to render.\n        page (bool): Render parses wrapped as full HTML page.\n        minify (bool): Minify HTML markup.\n        RETURNS (unicode): Rendered HTML markup.\n        \"\"\"\n        rendered = [self.render_ents(p['text'], p['ents'],\n                    p.get('title', None)) for p in parsed]\n        if page:\n            docs = ''.join([TPL_FIGURE.format(content=doc)\n                            for doc in rendered])\n            markup = TPL_PAGE.format(content=docs)\n        else:\n            markup = ''.join(rendered)\n        if minify:\n            return minify_html(markup)\n        return markup\n\n    def render_ents(self, text, spans, title):\n        \"\"\"Render entities in text.\n\n        text (unicode): Original text.\n        spans (list): Individual entity spans and their start, end and label.\n        title (unicode or None): Document title set in Doc.user_data['title'].\n        \"\"\"\n        markup = ''\n        offset = 0\n        for span in spans:\n            label = span['label']\n            start = span['start']\n            end = span['end']\n            entity = text[start:end]\n            fragments = text[offset:start].split('\\n')\n            for i, fragment in enumerate(fragments):\n                markup += fragment\n                if len(fragments) > 1 and i != len(fragments)-1:\n                    markup += '</br>'\n            if self.ents is None or label.upper() in self.ents:\n                color = self.colors.get(label.upper(), self.default_color)\n                markup += TPL_ENT.format(label=label, text=entity, bg=color)\n            else:\n                markup += entity\n            offset = end\n        markup += text[offset:]\n        markup = TPL_ENTS.format(content=markup, colors=self.colors)\n        if title:\n            markup = TPL_TITLE.format(title=title) + markup\n        return markup\n", "path": "spacy/displacy/render.py"}]}