I'm trying to draw graph (inline) of nltk
inside of jupyter-notebook
. But got error:
TclError: no display name and no $DISPLAY environment variable
I have tried to set $DISPLAY
to different values:
$env DISPLAY=0.0
# or
$env DISPLAY=inline
# or
$env DISPLAY=
but got error (or similar):
TclError: couldn't connect to display "0.0"
here is my code https://github.com/hyzhak/nltk-experiments/blob/master/main.ipynb the last cell.
Environment: official anaconda3 docker -- continuumio/anaconda3:4.4.0
https://github.com/ContinuumIO/docker-images. With nltk==3.2.3
inside.
Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58)
Type "copyright", "credits" or "license" for more information.
IPython 5.3.0 -- An enhanced Interactive Python.
How could I solve this error and inline nltk
graph inside of jupyter notebook
?
Update 1
http://www.nltk.org/_modules/nltk/draw/tree.html#draw_trees according to the sources of nltk tree draw it uses tkinter
.
Update 2
I have asked the same question in official nltk github repository https://github.com/nltk/nltk/issues/1765
Update 3
I think the reason of error could be the headless host (docker). I have installed xvfb
but seems it is note enough.
RUN apt-get install -y xvfb
Solution
I thought that xvfb
is launched by default but It should be run explicitly. So after I have launched it I could make screenshots of nltk tree graph.
import os
import nltk
from IPython.display import Image
chunkGram = r"""Chunk: {<RB.?>*<VB.?>*<NNP>+<NN>?}"""
chunkParser = nltk.RegexpParser(chunkGram)
tagged = [('Tonight', 'NN'), ('we', 'PRP'), ('are', 'VBP'), ('comforted', 'VBN'), ('by', 'IN'), ('the', 'DT'), ('hope', 'NN'), ('of', 'IN'), ('a', 'DT'), ('glad', 'JJ'), ('reunion', 'NN'), ('with', 'IN'), ('the', 'DT'), ('husband', 'NN'), ('who', 'WP'), ('was', 'VBD'), ('taken', 'VBN'), ('so', 'RB'), ('long', 'RB'), ('ago', 'RB'), (',', ','), ('and', 'CC'), ('we', 'PRP'), ('are', 'VBP'), ('grateful', 'JJ'), ('for', 'IN'), ('the', 'DT'), ('good', 'JJ'), ('life', 'NN'), ('of', 'IN'), ('Coretta', 'NNP'), ('Scott', 'NNP'), ('King', 'NNP'), ('.', '.')]
chunked = chunkParser.parse(tagged)
nltk.draw.tree.TreeView(chunked)._cframe.print_to_file('output.ps')
os.system('convert output.ps output.png')
Image(filename='output.png')
[out]:
Try incorporating the following snippet in your code
import os
import matplotlib as mpl
if os.environ.get('DISPLAY','') == '':
print('no display found. Using non-interactive Agg backend')
mpl.use('Agg')
import matplotlib.pyplot as plt
Regardless. Your problem is that Matplotlib's default call to an x-using backend is apparently causing a problem. This answer is by no means the only possible solution, but I think this will solve your problem.
Remember that it is important to switch backend before importing pyplot.
Alternatively, you could try
IPython.core.display.display(chunked)
Make sure that your notebook server is started with the -X flag set..
def jupyter_draw_nltk_tree(tree):
from IPython.display import Image, display
from nltk.draw import TreeWidget
from nltk.draw.util import CanvasFrame
import subprocess
cf = CanvasFrame()
tc = TreeWidget(cf.canvas(), tree)
tc['node_font'] = 'arial 13 bold'
tc['leaf_font'] = 'arial 14'
tc['node_color'] = '#005990'
tc['leaf_color'] = '#3F8F57'
tc['line_color'] = '#175252'
cf.add_widget(tc, 10, 10)
cf.print_to_file('tmp_tree_output.ps')
cf.destroy()
args = (['convert', 'tmp_tree_output.ps', 'tmp_tree_output.png'])
subprocess.call(args)
display(Image(filename='tmp_tree_output.png'))
os.system('rm tmp_tree_output.ps tmp_tree_output.png')
jupyter_draw_nltk_tree(chunked)