def jupyter_draw_nltk_tree(tree: Tree = None,
                           directory: str = '/tmp',
                           f_name: str = 'tmp',
                           show_tree: bool = False):
    f_name = Path(directory) / f_name
    f_name.parent.mkdir(exist_ok=True, parents=True)

    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, 20, 20)
    ps_file_name = f_name.with_suffix('.ps').as_posix()
    cf.print_to_file(ps_file_name)
    cf.destroy()

    png_file_name = f_name.with_suffix(".png").as_posix()
    system(f'convert {ps_file_name} {png_file_name}')

    if show_tree:
        display((Image(filename=png_file_name), ))

    system(f'rm {f_name}.ps')

    return png_file_name
Example #2
0
def save_tree(tree, d, name, postscript=False, **kwargs):
    drawable_tree = tree if d is None else get_drawable_tree(tree[0], d)
    extension = 'ps' if postscript else 'png'
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), drawable_tree)
    tc['node_font'] = 'arial 22 bold'
    tc['leaf_font'] = 'arial 22'
    tc['node_color'] = '#005990'
    tc['leaf_color'] = '#3F8F57'
    tc['line_color'] = '#175252'
    tc['xspace'] = 20
    tc['yspace'] = 20
    curr_y = 40 * len(kwargs)
    cf.add_widget(tc, 0, curr_y)
    cf.print_to_file('{0}.{1}'.format(name, extension))
    if not postscript:
        im1 = Image.open('{0}.{1}'.format(name, extension))
        im1 = im1.convert('RGB')
        curr_y = 10
        for key in kwargs:
            font = ImageFont.truetype("/fonts/Ubuntu-L.ttf", 24)
            draw = ImageDraw.Draw(im1)
            val = kwargs[key]
            format_str = '{0}'
            if isinstance(val, float):
                format_str = format_str + '={1:.4f}'
            else:
                format_str = format_str + '=  {1}'
            draw.text((10, curr_y), format_str.format(key, val), (0, 0, 0),
                      font)
            curr_y = curr_y + 40
        im1.save('{}.pdf'.format(name))
        cf.destroy()
        os.remove('{0}.{1}'.format(name, extension))
    return '{0}.{1}'.format(name, 'ps' if postscript else 'pdf')
Example #3
0
def quicktree(sentence):
    """Parse a sentence and return a visual representation in IPython"""
    import os
    from nltk import Tree
    from nltk.draw.util import CanvasFrame
    from nltk.draw import TreeWidget
    from stat_parser import Parser
    try:
        from IPython.display import display
        from IPython.display import Image
    except:
        pass
    try:
        get_ipython().getoutput()
    except TypeError:
        have_ipython = True
    except NameError:
        import subprocess
        have_ipython = False
    parser = Parser()
    parsed = parser.parse(sentence)
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), parsed)
    cf.add_widget(tc, 10, 10)  # (10,10) offsets
    cf.print_to_file('tree.ps')
    cf.destroy()
    if have_ipython:
        tregex_command = 'convert tree.ps tree.png'
        result = get_ipython().getoutput(tregex_command)
    else:
        tregex_command = ["convert", "tree.ps", "tree.png"]
        result = subprocess.check_output(tregex_command)
    os.remove("tree.ps")
    return Image(filename='tree.png')
    os.remove("tree.png")
Example #4
0
def save_tree(tree):
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(),tree)
    cf.add_widget(tc,10,10) # (10,10) offsets
    cf.print_to_file('tree.ps')
    cf.destroy()
    os.system('convert tree.ps output.png')
Example #5
0
def draw_tree_to_file(tree, path):
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), tree)
    x, y = 0, 0
    cf.add_widget(tc, x, y)
    cf.print_to_file(path)
    cf.destroy()
Example #6
0
def quicktree(sentence):
    """Parse a sentence and return a visual representation in IPython"""
    import os
    from nltk import Tree
    from nltk.draw.util import CanvasFrame
    from nltk.draw import TreeWidget
    from stat_parser import Parser
    try:
        from IPython.display import display
        from IPython.display import Image
    except:
        pass
    try:
        get_ipython().getoutput()
    except TypeError:
        have_ipython = True
    except NameError:
        import subprocess
        have_ipython = False
    parser = Parser()
    parsed = parser.parse(sentence)
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(),parsed)
    cf.add_widget(tc,10,10) # (10,10) offsets
    cf.print_to_file('tree.ps')
    cf.destroy()
    if have_ipython:
        tregex_command = 'convert tree.ps tree.png'
        result = get_ipython().getoutput(tregex_command)
    else:
        tregex_command = ["convert", "tree.ps", "tree.png"]
        result = subprocess.check_output(tregex_command)    
    os.remove("tree.ps")
    return Image(filename='tree.png')
    os.remove("tree.png")
Example #7
0
def format(sentence):
    filename = 'stanford-parser.jar'
    command = ['locate', filename]
    output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0]
    path_to_jar = output.decode().strip()

    filename = 'models.jar'
    command = ['locate', filename]
    output = subprocess.Popen(
        command, stdout=subprocess.PIPE).communicate()[0].decode().strip()
    output = output.split('\n')
    for op in output:
        if 'parse' in op:
            path_to_models_jar = op

    dependency_parser = StanfordDependencyParser(
        path_to_jar=path_to_jar, path_to_models_jar=path_to_models_jar)
    tokens = word_tokenize(sentence)
    result = dependency_parser.raw_parse(sentence)

    for dep in result:
        # print(dep.tree())
        cf = CanvasFrame()
        t = dep.tree()
        tc = TreeWidget(cf.canvas(), t)
        cf.add_widget(tc, 10, 10)  # (10,10) offsets
        cf.print_to_file('tree.ps')
        cf.destroy()
        return (dep, tokens)
Example #8
0
    def write_tree_stream(self, nltk_tree):
        """
        Draws and outputs in PNG for ipython.
        PNG is used instead of PDF, since it can be displayed in the qt console and
        has wider browser support.
        """
        import os
        import base64
        import subprocess
        import tempfile
        from nltk.draw.tree import tree_to_treesegment
        from nltk.draw.util import CanvasFrame
        from nltk.internals import find_binary

        _canvas_frame = CanvasFrame()
        # widget = tree_to_treesegment(_canvas_frame.canvas(), self)
        widget = tree_to_treesegment(_canvas_frame.canvas(), nltk_tree)
        _canvas_frame.add_widget(widget)
        x, y, w, h = widget.bbox()
        # print_to_file uses scrollregion to set the width and height of the pdf.
        _canvas_frame.canvas()["scrollregion"] = (0, 0, w, h)
        with tempfile.NamedTemporaryFile() as file:
            in_path = "{0:}.ps".format(file.name)
            out_path = "{0:}.png".format(file.name)
            _canvas_frame.print_to_file(in_path)
            _canvas_frame.destroy_widget(widget)
            try:
                subprocess.call([
                    find_binary(
                        "gs",
                        binary_names=["gswin32c.exe", "gswin64c.exe"],
                        env_vars=["PATH"],
                        verbose=False,
                    )
                ] + "-q -dEPSCrop -sDEVICE=png16m -r90 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -dSAFER -dBATCH -dNOPAUSE -sOutputFile={0:} {1:}"
                                .format(out_path, in_path).split())
            except LookupError:
                pre_error_message = str(
                    "The Ghostscript executable isn't found.\n"
                    "See http://web.mit.edu/ghostscript/www/Install.htm\n"
                    "If you're using a Mac, you can try installing\n"
                    "https://docs.brew.sh/Installation then `brew install ghostscript`"
                )
                print(pre_error_message, file=sys.stderr)
                raise LookupError

            with open(out_path, "rb") as sr:
                res = sr.read()
                b = bytearray(res)
                # b0 = b[0]
            os.remove(in_path)
            os.remove(out_path)
            # return base64.b64encode(res).decode()
            # return base64.b64encode(res)

            # return b0
            return b
def draw_to_file(tree):
    canvas = CanvasFrame()
    tree_canvas = TreeWidget(canvas.canvas(), tree)
    canvas.add_widget(tree_canvas, 10, 10)

    file_name = 'tree_plot.ps'

    canvas.print_to_file(file_name)
    canvas.destroy()
def draw_nltk_tree(tree):
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), tree)
    tc['node_font'] = 'arial 15 bold'
    tc['leaf_font'] = 'arial 15'
    tc['node_color'] = '#005990'
    tc['leaf_color'] = '#3F8F57'
    tc['line_color'] = '#175252'
    cf.add_widget(tc, 50, 50)
    cf.print_to_file('tmp_tree_output.ps')
    cf.destroy()
Example #11
0
def drawrst(strtree, fname):
    """ Draw RST tree into a file
    """
    if not fname.endswith(".ps"):
        fname += ".ps"
    cf = CanvasFrame()
    t = Tree.fromstring(strtree)
    tc = TreeWidget(cf.canvas(), t)
    cf.add_widget(tc,10,10) # (10,10) offsets
    cf.print_to_file(fname)
    cf.destroy()
Example #12
0
 def draw_rst(self, fname):
     """ Draw RST tree into a file
     """
     tree_str = self.get_parse()
     if not fname.endswith(".ps"):
         fname += ".ps"
     cf = CanvasFrame()
     t = Tree.fromstring(tree_str)
     tc = TreeWidget(cf.canvas(), t)
     cf.add_widget(tc, 10, 10)  # (10,10) offsets
     cf.print_to_file(fname)
     cf.destroy()
Example #13
0
def save_tree_with_ps(str_tree, save_path):
	# 输出可视化结果
	cf = CanvasFrame()
	tc = TreeWidget(cf.canvas(), str_tree)
	tc['node_font'] = 'arial 14 bold'
	tc['leaf_font'] = 'arial 14'
	tc['node_color'] = '#005990'
	tc['leaf_color'] = '#3F8F57'
	tc['line_color'] = '#175252'
	cf.add_widget(tc, 10, 10) # (10,10) offsets
	cf.print_to_file('{}.ps'.format(save_path))
	cf.destroy()
Example #14
0
def draw_tree(tree_string):
    raise NotImplementedError()

    from nltk import Tree
    from nltk.draw.util import CanvasFrame
    from nltk.draw import TreeWidget

    cf = CanvasFrame()
    tree = Tree.fromstring(tree_string.replace('[','(').replace(']',')') )
    cf.add_widget(TreeWidget(cf.canvas(), tree), 10, 10)
    cf.print_to_file('tree.ps')
    cf.destroy
Example #15
0
def drawTreeAndSaveImage(s, i, dir):
    parsed_sent = parser.raw_parse(s)
    for line in parsed_sent:
        cf = CanvasFrame()
        t = Tree.fromstring(str(line))
        tc = TreeWidget(cf.canvas(), t)
        cf.add_widget(tc, 10, 10)
        i += 1
        cf.print_to_file(dir + str(i) + '.ps')
        tree_name = dir + str(i) + '.ps'
        tree_new_name = dir + str(i) + '.png'
        os.system('convert ' + tree_name + ' ' + tree_new_name)
        cf.destroy()
 def draw_nltk_tree(tree):
     cf = CanvasFrame()
     tc = TreeWidget(cf.canvas(), tree)
     tc['node_font'] = 'arial 15 bold'
     tc['leaf_font'] = 'arial 15'
     tc['node_color'] = '#005990'
     tc['leaf_color'] = '#3F8F57'
     tc['line_color'] = '#175252'
     cf.add_widget(tc, 50, 50)
     cf.print_to_file('tmp_tree_output.ps')
     cf.destroy()
     os.system('convert tmp_tree_output.ps tmp_tree_output.png')
     display(Image(filename='tmp_tree_output.png'))
def quicktree(sentence):
    """Parse a sentence and return a visual representation"""
    from nltk import Tree
    from nltk.draw.util import CanvasFrame
    from nltk.draw import TreeWidget
    from stat_parser import Parser
    from IPython.display import display
    from IPython.display import Image
    parser = Parser()
    parsed = parser.parse(sentence)
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), parsed)
    cf.add_widget(tc, 10, 10)  # (10,10) offsets
    cf.print_to_file('tree.ps')
    cf.destroy()
Example #18
0
def save_tree(str_tree, save_path):
	# 输出可视化结果
	cf = CanvasFrame()
	tc = TreeWidget(cf.canvas(), str_tree)
	tc['node_font'] = 'arial 14 bold'
	tc['leaf_font'] = 'arial 14'
	tc['node_color'] = '#005990'
	tc['leaf_color'] = '#3F8F57'
	tc['line_color'] = '#175252'
	cf.add_widget(tc, 10, 10) # (10,10) offsets
	cf.print_to_file('tmp.ps')
	cf.destroy()

	# 使用ImageMagick工具进行转换
	lake.shell.run('convert tmp.ps %s' % save_path)
	lake.shell.run('rm tmp.ps')
Example #19
0
def main(args):
    """
    Subcommand main.

    You shouldn't need to call this yourself if you're using
    `config_argparser`
    """
    corpus = read_corpus(args)
    odir = get_output_dir(args)
    for key in corpus:
        cframe = CanvasFrame()
        widget = TreeWidget(cframe.canvas(), corpus[key])
        cframe.add_widget(widget, 10, 10)
        ofilename = fp.join(odir, key.doc) + '.ps'
        cframe.print_to_file(ofilename)
        cframe.destroy()
    announce_output_dir(odir)
Example #20
0
	def execute(self, frase):

		os.environ['STANFORD_PARSER'] = 'nltk/stanford-parser.jar'
		os.environ['STANFORD_MODELS'] = 'nltk/stanford-parser-3.5.2-models.jar'

		parser = stanford.StanfordParser(model_path="nltk/englishPCFG.ser.gz")
		sentence = parser.raw_parse(frase)
		print sentence

		# GUI
		for line in sentence:
			cf = CanvasFrame()
			tc = TreeWidget(cf.canvas(),line)
			cf.add_widget(tc,40,40) # (10,10) offsets
			cf.print_to_file('tree_stanford.ps')
			#cf.destroy()
			os.popen('convert tree_stanford.ps -resize 300% static/img/tree_stanford.png')
Example #21
0
def main(args):
    """
    Subcommand main.

    You shouldn't need to call this yourself if you're using
    `config_argparser`
    """
    corpus = read_corpus(args)
    odir = get_output_dir(args)
    for key in corpus:
        cframe = CanvasFrame()
        widget = TreeWidget(cframe.canvas(), corpus[key])
        cframe.add_widget(widget, 10, 10)
        ofilename = fp.join(odir, key.doc) + '.ps'
        cframe.print_to_file(ofilename)
        cframe.destroy()
    announce_output_dir(odir)
Example #22
0
def display_tree(tree):
    if nltk_is_available:
        count = 0
        for t in tree:
            cf = CanvasFrame()
            tc = TreeWidget(cf.canvas(), t)
            cf.add_widget(tc, 10, 10)
            count += 1
            fileName = "tree" + repr(count) + ".ps"
            cf.print_to_file(fileName)
            cf.destroy()
    else:
        count = 0
        for t in tree:
            count += 1
            fileName = "tree" + repr(count) + ".txt"
            pprint.pprint(t, fileName)
def draw_nltk_tree(tree):
    # Borrowed from
    # https://stackoverflow.com/questions/31779707/how-do-you-make-nltk-draw-trees-that-are-inline-in-ipython-jupyter

    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), tree)
    tc['node_font'] = 'arial 15 bold'
    tc['leaf_font'] = 'arial 15'
    tc['node_color'] = '#005990'
    tc['leaf_color'] = '#3F8F57'
    tc['line_color'] = '#175252'
    cf.add_widget(tc, 50, 50)
    cf.print_to_file('tmp_tree_output.ps')
    cf.destroy()
    os.system('convert tmp_tree_output.ps tmp_tree_output.png')
    display(Image(filename='tmp_tree_output.png'))
    os.system('rm tmp_tree_output.ps tmp_tree_output.png')
Example #24
0
def format(sentence, jar_location):
    path_to_jar = jar_location + '/stanford-parser.jar'
    path_to_models_jar = jar_location + '/stanford-parser-3.9.2-models.jar'

    dependency_parser = StanfordDependencyParser(
        path_to_jar=path_to_jar, path_to_models_jar=path_to_models_jar)
    tokens = word_tokenize(sentence)
    result = dependency_parser.raw_parse(sentence)

    for dep in result:
        # print(dep.tree())
        cf = CanvasFrame()
        t = dep.tree()
        tc = TreeWidget(cf.canvas(), t)
        cf.add_widget(tc, 10, 10)
        cf.print_to_file('tree.ps')
        cf.destroy()
        return (dep, tokens)
Example #25
0
def draw_trees(trees, name, reverse_dict=None, print_prob=False):
    for ind, tree in enumerate(trees):
        if reverse_dict:
            change_leaves(tree[0], reverse_dict)
        in_row = 1
        len_one = 140
        height = 200
        i = 0
        cf = CanvasFrame()
        tc = TreeWidget(cf.canvas(), tree[0])
        x, y = (i % in_row) * len_one, int(i / in_row) * height
        cf.add_widget(tc, x, y)
        if print_prob:
            tp = TreeWidget(cf.canvas(), tree[1])
            cf.add_widget(tp, x + len_one, y)
        i = i + 1
        cf.print_to_file('{0}{1}.ps'.format(name, ind))
        cf.destroy()
Example #26
0
	def tagger(self, frase):
		#hacer el tag
		text = nltk.word_tokenize(frase)
		postag = nltk.pos_tag(text)

		#convertirlo al formato lips
		result = "("
		
		for index in range(len(postag)):
			result +=  "( " + postag[index][0] + " ( " + postag[index][1]+ " ) )"

		result += ")"

		#ejecutar bikel

		#pasar resultado a archivo
		#hoy = str(datetime.date.today())

		f = open('prueba', 'w')
		f.write(result)
		f.close()
		
		#consola = os.popen('tcsh ../dbparser/bin/parse 400 ../dbparser/settings/collins.properties ../wsj-02-21.obj.gz prueba')

		args = shlex.split("tcsh ../dbparser/bin/parse 400 ../dbparser/settings/collins.properties ../wsj-02-21.obj.gz prueba")
		print args

		p = subprocess.Popen(args,stderr=subprocess.STDOUT)
		p.wait()

		f2 = open('prueba.parsed', 'r')
		resultado = f2.read()

		t = Tree.fromstring(resultado)

		cf = CanvasFrame()
		tc = TreeWidget(cf.canvas(),t)
		cf.add_widget(tc,40,40) # (10,10) offsets
		cf.print_to_file('tree_bikel.ps')
		#cf.destroy()
		os.popen('convert tree_bikel.ps -resize 300% static/img/tree_bikel.png')
		

		return resultado
Example #27
0
def tree_to_ps(s, outfile):
    global _canvas_frame
    if _canvas_frame is None:
        _canvas_frame = CanvasFrame()

    # May throw ValueError:
    widget = tree_to_widget(s, _canvas_frame.canvas())

    _canvas_frame.canvas()['scrollregion'] = (0, 0, 1, 1)
    _canvas_frame.add_widget(widget)
    _canvas_frame.print_to_file(outfile)
    bbox = widget.bbox()
    _canvas_frame.destroy_widget(widget)

    ## Testing..
    #for (key, val) in metrics.items():
    #    print key, '\n  ', val
    
    return bbox[2:]
Example #28
0
def tree_to_ps(s, outfile):
    global _canvas_frame
    if _canvas_frame is None:
        _canvas_frame = CanvasFrame()

    # May throw ValueError:
    widget = tree_to_widget(s, _canvas_frame.canvas())

    _canvas_frame.canvas()['scrollregion'] = (0, 0, 1, 1)
    _canvas_frame.add_widget(widget)
    _canvas_frame.print_to_file(outfile)
    bbox = widget.bbox()
    _canvas_frame.destroy_widget(widget)

    ## Testing..
    #for (key, val) in metrics.items():
    #    print key, '\n  ', val

    return bbox[2:]
Example #29
0
def create_tree_ps(parse_tree):
    cf = CanvasFrame(width=550, height=450, closeenough=2)

    t = Tree.fromstring(parse_tree)

    tc = TreeWidget(
        cf.canvas(),
        t,
        draggable=1,
        node_font=("helvetica", -14, "bold"),
        leaf_font=("helvetica", -12, "italic"),
        roof_fill="white",
        roof_color="black",
        leaf_color="green4",
        node_color="blue2",
    )
    cf.add_widget(tc, 10, 10)

    cf.print_to_file(constants.QIK_DATA_DIR + "query_parse_tree.ps")
Example #30
0
def draw_one_tree(strtree, draw_file):
    cf = CanvasFrame()
    t = Tree.fromstring(strtree)
    tc = TreeWidget(cf.canvas(), t, draggable=1)
    cf.add_widget(tc, 1200, 0)  # (10,10) offsets
    # edus 文本
    edus_txt = ""
    c = cf.canvas()
    edu_path = RAW_TXT + "/" + draw_file.split("/")[2].split(
        ".")[0] + ".out.edu"
    with open(edu_path, "r") as f:
        for line in f:
            edus_txt += line
    edus_txt = TextWidget(c, edus_txt, draggable=1)
    cf.add_widget(edus_txt, 1400, 0)
    user_choice = input("直接打印(a) or 存到文件(b): ")
    if user_choice == "a":
        cf.mainloop()
    else:
        cf.print_to_file(draw_file)
        cf.destroy()
Example #31
0
def build_syntax_tree(txt):
    sentences = nltk.sent_tokenize(txt)
    for sent in sentences:
        tsent = pos_tag_sentence(sent, 'tree')
        ch = nltk.RegexpParser(grammar)
        tree = ch.parse(tsent)

        cf = CanvasFrame()
        tc = TreeWidget(cf.canvas(), tree)
        tc['node_font'] = 'arial 14 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(path + 'tree.ps')
        cf.destroy()

        os.system('convert {0}tree.ps {0}tree.png'.format(path))

        return open(path + 'tree.png', 'rb')
Example #32
0
def save_image(parsed, index: str) -> Binary:
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), parsed, xspace=40, yspace=40)
    tc['node_font'] = 'arial 20 bold'
    tc['leaf_font'] = 'arial 20 bold'
    tc['node_color'] = '#005990'
    tc['leaf_color'] = '#3F8F57'
    tc['line_color'] = '#175252'
    cf.add_widget(tc, 50, 50)

    cf.print_to_file(os.path.join(trees_path, f'tree_{index}.ps'))
    cf.destroy()

    os.system(f'convert {trees_path}/tree_{index}.ps '
              f'{trees_path}/tree_{index}.png')
    os.remove(f'{trees_path}/tree_{index}.ps')

    with open(f'{trees_path}/tree_{index}.png', 'rb') as tree_img:
        tree_bin = Binary(tree_img.read())

    return tree_bin
Example #33
0
    def convertPsToPng(self, treeVal):
        cf = CanvasFrame()

        tr = Tree.fromstring(treeVal)
        tc = TreeWidget(cf.canvas(), tr)

        tc['node_font'] = 'arial 13 bold'
        tc['leaf_font'] = 'arial 11'
        tc['node_color'] = '#005990'
        tc['leaf_color'] = '#3F8F57'
        tc['line_color'] = '#175252'
        tc['xspace'] = 25
        tc['yspace'] = 25

        cf.add_widget(tc, 10, 10)  # (10,10) offsets

        cf.print_to_file(self.filenamePS)
        cf.destroy()

        #MagickImage doit etre installée ainsi que convert
        os.system("convert %s %s" % (self.filenamePS, self.filenamePNG))
Example #34
0
    def to_ps(self, filename):
        """Export as a PostScript image.

        This function is used by `_repr_png_`.
        """
        _canvas_frame = CanvasFrame()
        # WIP customization of visual appearance
        # NB: conda-provided python and tk cannot access most fonts on the
        # system, thus it currently falls back on the default font
        widget = tree_to_treesegment(_canvas_frame.canvas(), self,
                                     tree_yspace=35,
                                     node_font=('Verdana', -18, 'bold'),
                                     leaf_font=('Verdana', -18))
        _canvas_frame.add_widget(widget)
        x, y, w, h = widget.bbox()
        # print_to_file uses scrollregion to set the width and height of the
        # pdf
        _canvas_frame.canvas()['scrollregion'] = (0, 0, w, h)
        # print to file
        _canvas_frame.print_to_file(filename)
        _canvas_frame.destroy_widget(widget)
Example #35
0
    def to_ps(self, filename):
        """Export as a PostScript image.

        This function is used by `_repr_png_`.
        """
        _canvas_frame = CanvasFrame()
        # WIP customization of visual appearance
        # NB: conda-provided python and tk cannot access most fonts on the
        # system, thus it currently falls back on the default font
        widget = tree_to_treesegment(_canvas_frame.canvas(),
                                     self,
                                     tree_yspace=35,
                                     node_font=('Verdana', -18, 'bold'),
                                     leaf_font=('Verdana', -18))
        _canvas_frame.add_widget(widget)
        x, y, w, h = widget.bbox()
        # print_to_file uses scrollregion to set the width and height of the
        # pdf
        _canvas_frame.canvas()['scrollregion'] = (0, 0, w, h)
        # print to file
        _canvas_frame.print_to_file(filename)
        _canvas_frame.destroy_widget(widget)
def make_tree_png(sentence, file_number, sentence_number, outputDirectory):
    '''
    sentence: bracket notation of the sentence
    file_number: file the sentence originates from
    sentence_number: number of sentences
    outputDirectory: directory for the files (has to exist)
    Creates a png image with a syntax tree from the bracket notation of the given sentence
    '''
    filename = 'parse{}_sentence{}'.format(file_number, sentence_number)
    # make syntax tree using nltk
    cf = CanvasFrame()
    t = Tree.fromstring(sentence) # make tree from sentence
    tc = TreeWidget(cf.canvas(),t)
    cf.add_widget(tc,10,10) # (10,10) offsets
    cf.print_to_file('./{}/{}.ps'.format(outputDirectory, filename)) # print tree in a .ps file
    cf.destroy()

    # convert the ps files to usable (non-transparent) png images
    filepath = "./{}/{}".format(outputDirectory, filename)

    os.system('convert {}.ps {}.png'.format(filepath, filepath)) #convert to png
    os.system('convert -flatten {}.png {}.png'.format(filepath, filepath)) #make bg white
    os.system('del ".\{}\{}.ps"'.format(outputDirectory, filename)) #delete old .ps files
Example #37
0
def save_tree(sentence):

    name = hashlib.md5(sentence).hexdigest()

    result = loads(server.parse(sentence))

    if os.path.exists(os.path.join(path, "{0}.jpg".format(name))):
        print "File exists"

    else:
        with cd(path):
            try:

                tree = result["sentences"][0]["parsetree"]
            except Exception as e:
                print "Error %s occurred while processing the sentence %s" % (
                    e, sentence)
                return [None, None, None]

            cf = CanvasFrame()
            t = nltk.tree.Tree.fromstring(tree)
            tc = TreeWidget(cf.canvas(), t)
            cf.add_widget(tc, 10, 10)  # (10,10) offsets
            cf.print_to_file('{0}.ps'.format(name))
            subprocess.call([
                "convert", "-density", "100", "{0}.ps".format(name), "-resize",
                "100%", "-gamma", "2.2", "-quality", "92",
                "{0}.jpg".format(name)
            ])
            #subprocess.call(["convert",  "{0}.ps".format(name), "{0}.jpg".format(name)])
            cf.destroy()

    return [
        "{0}/{1}.jpg".format(path,
                             name), result["sentences"][0]["dependencies"],
        result["sentences"][0]["indexeddependencies"]
    ]
Example #38
0
from nltk.draw import TreeWidget

for auteur in auteurs:
    for article in range(10):
        # Chargement des fichiers
        chemin = './articles_arbres/'+auteur+'/'+str(article)+'.txt'
        fichier = open(chemin, 'rb')
        A = pickle.load(fichier)
        fichier.close()
        # Impression des arbres
        #A[0].draw()
        cf = CanvasFrame()
        t = A[0]
        tc = TreeWidget(cf.canvas(),t)
        cf.add_widget(tc,10,10) # (10,10) offsets
        cf.print_to_file('./dessins_arbres/'+auteur+'/'+str(article)+'.ps')
        cf.destroy()
    
    
    
    
    
    
    
    
    
    
    
    
    
    
Example #39
0
class ShiftReduceApp(object):
    """
    A graphical tool for exploring the shift-reduce parser.  The tool
    displays the parser's stack and the remaining text, and allows the
    user to control the parser's operation.  In particular, the user
    can shift tokens onto the stack, and can perform reductions on the
    top elements of the stack.  A "step" button simply steps through
    the parsing process, performing the operations that
    ``nltk.parse.ShiftReduceParser`` would use.
    """
    def __init__(self, grammar, sent, trace=0):
        self._sent = sent
        self._parser = SteppingShiftReduceParser(grammar, trace)

        # Set up the main window.
        self._top = Tk()
        self._top.title('Shift Reduce Parser Application')

        # Animations.  animating_lock is a lock to prevent the demo
        # from performing new operations while it's animating.
        self._animating_lock = 0
        self._animate = IntVar(self._top)
        self._animate.set(10) # = medium

        # The user can hide the grammar.
        self._show_grammar = IntVar(self._top)
        self._show_grammar.set(1)

        # Initialize fonts.
        self._init_fonts(self._top)

        # Set up key bindings.
        self._init_bindings()

        # Create the basic frames.
        self._init_menubar(self._top)
        self._init_buttons(self._top)
        self._init_feedback(self._top)
        self._init_grammar(self._top)
        self._init_canvas(self._top)

        # A popup menu for reducing.
        self._reduce_menu = Menu(self._canvas, tearoff=0)

        # Reset the demo, and set the feedback frame to empty.
        self.reset()
        self._lastoper1['text'] = ''

    #########################################
    ##  Initialization Helpers
    #########################################

    def _init_fonts(self, root):
        # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html>
        self._sysfont = tkinter.font.Font(font=Button()["font"])
        root.option_add("*Font", self._sysfont)

        # TWhat's our font size (default=same as sysfont)
        self._size = IntVar(root)
        self._size.set(self._sysfont.cget('size'))

        self._boldfont = tkinter.font.Font(family='helvetica', weight='bold',
                                    size=self._size.get())
        self._font = tkinter.font.Font(family='helvetica',
                                    size=self._size.get())

    def _init_grammar(self, parent):
        # Grammar view.
        self._prodframe = listframe = Frame(parent)
        self._prodframe.pack(fill='both', side='left', padx=2)
        self._prodlist_label = Label(self._prodframe,
                                     font=self._boldfont,
                                     text='Available Reductions')
        self._prodlist_label.pack()
        self._prodlist = Listbox(self._prodframe, selectmode='single',
                                 relief='groove', background='white',
                                 foreground='#909090',
                                 font=self._font,
                                 selectforeground='#004040',
                                 selectbackground='#c0f0c0')

        self._prodlist.pack(side='right', fill='both', expand=1)

        self._productions = list(self._parser.grammar().productions())
        for production in self._productions:
            self._prodlist.insert('end', (' %s' % production))
        self._prodlist.config(height=min(len(self._productions), 25))

        # Add a scrollbar if there are more than 25 productions.
        if 1:#len(self._productions) > 25:
            listscroll = Scrollbar(self._prodframe,
                                   orient='vertical')
            self._prodlist.config(yscrollcommand = listscroll.set)
            listscroll.config(command=self._prodlist.yview)
            listscroll.pack(side='left', fill='y')

        # If they select a production, apply it.
        self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select)

        # When they hover over a production, highlight it.
        self._hover = -1
        self._prodlist.bind('<Motion>', self._highlight_hover)
        self._prodlist.bind('<Leave>', self._clear_hover)

    def _init_bindings(self):
        # Quit
        self._top.bind('<Control-q>', self.destroy)
        self._top.bind('<Control-x>', self.destroy)
        self._top.bind('<Alt-q>', self.destroy)
        self._top.bind('<Alt-x>', self.destroy)

        # Ops (step, shift, reduce, undo)
        self._top.bind('<space>', self.step)
        self._top.bind('<s>', self.shift)
        self._top.bind('<Alt-s>', self.shift)
        self._top.bind('<Control-s>', self.shift)
        self._top.bind('<r>', self.reduce)
        self._top.bind('<Alt-r>', self.reduce)
        self._top.bind('<Control-r>', self.reduce)
        self._top.bind('<Delete>', self.reset)
        self._top.bind('<u>', self.undo)
        self._top.bind('<Alt-u>', self.undo)
        self._top.bind('<Control-u>', self.undo)
        self._top.bind('<Control-z>', self.undo)
        self._top.bind('<BackSpace>', self.undo)

        # Misc
        self._top.bind('<Control-p>', self.postscript)
        self._top.bind('<Control-h>', self.help)
        self._top.bind('<F1>', self.help)
        self._top.bind('<Control-g>', self.edit_grammar)
        self._top.bind('<Control-t>', self.edit_sentence)

        # Animation speed control
        self._top.bind('-', lambda e,a=self._animate:a.set(20))
        self._top.bind('=', lambda e,a=self._animate:a.set(10))
        self._top.bind('+', lambda e,a=self._animate:a.set(4))

    def _init_buttons(self, parent):
        # Set up the frames.
        self._buttonframe = buttonframe = Frame(parent)
        buttonframe.pack(fill='none', side='bottom')
        Button(buttonframe, text='Step',
               background='#90c0d0', foreground='black',
               command=self.step,).pack(side='left')
        Button(buttonframe, text='Shift', underline=0,
               background='#90f090', foreground='black',
               command=self.shift).pack(side='left')
        Button(buttonframe, text='Reduce', underline=0,
               background='#90f090', foreground='black',
               command=self.reduce).pack(side='left')
        Button(buttonframe, text='Undo', underline=0,
               background='#f0a0a0', foreground='black',
               command=self.undo).pack(side='left')

    def _init_menubar(self, parent):
        menubar = Menu(parent)

        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label='Reset Parser', underline=0,
                             command=self.reset, accelerator='Del')
        filemenu.add_command(label='Print to Postscript', underline=0,
                             command=self.postscript, accelerator='Ctrl-p')
        filemenu.add_command(label='Exit', underline=1,
                             command=self.destroy, accelerator='Ctrl-x')
        menubar.add_cascade(label='File', underline=0, menu=filemenu)

        editmenu = Menu(menubar, tearoff=0)
        editmenu.add_command(label='Edit Grammar', underline=5,
                             command=self.edit_grammar,
                             accelerator='Ctrl-g')
        editmenu.add_command(label='Edit Text', underline=5,
                             command=self.edit_sentence,
                             accelerator='Ctrl-t')
        menubar.add_cascade(label='Edit', underline=0, menu=editmenu)

        rulemenu = Menu(menubar, tearoff=0)
        rulemenu.add_command(label='Step', underline=1,
                             command=self.step, accelerator='Space')
        rulemenu.add_separator()
        rulemenu.add_command(label='Shift', underline=0,
                             command=self.shift, accelerator='Ctrl-s')
        rulemenu.add_command(label='Reduce', underline=0,
                             command=self.reduce, accelerator='Ctrl-r')
        rulemenu.add_separator()
        rulemenu.add_command(label='Undo', underline=0,
                             command=self.undo, accelerator='Ctrl-u')
        menubar.add_cascade(label='Apply', underline=0, menu=rulemenu)

        viewmenu = Menu(menubar, tearoff=0)
        viewmenu.add_checkbutton(label="Show Grammar", underline=0,
                                 variable=self._show_grammar,
                                 command=self._toggle_grammar)
        viewmenu.add_separator()
        viewmenu.add_radiobutton(label='Tiny', variable=self._size,
                                 underline=0, value=10, command=self.resize)
        viewmenu.add_radiobutton(label='Small', variable=self._size,
                                 underline=0, value=12, command=self.resize)
        viewmenu.add_radiobutton(label='Medium', variable=self._size,
                                 underline=0, value=14, command=self.resize)
        viewmenu.add_radiobutton(label='Large', variable=self._size,
                                 underline=0, value=18, command=self.resize)
        viewmenu.add_radiobutton(label='Huge', variable=self._size,
                                 underline=0, value=24, command=self.resize)
        menubar.add_cascade(label='View', underline=0, menu=viewmenu)

        animatemenu = Menu(menubar, tearoff=0)
        animatemenu.add_radiobutton(label="No Animation", underline=0,
                                    variable=self._animate, value=0)
        animatemenu.add_radiobutton(label="Slow Animation", underline=0,
                                    variable=self._animate, value=20,
                                    accelerator='-')
        animatemenu.add_radiobutton(label="Normal Animation", underline=0,
                                    variable=self._animate, value=10,
                                    accelerator='=')
        animatemenu.add_radiobutton(label="Fast Animation", underline=0,
                                    variable=self._animate, value=4,
                                    accelerator='+')
        menubar.add_cascade(label="Animate", underline=1, menu=animatemenu)


        helpmenu = Menu(menubar, tearoff=0)
        helpmenu.add_command(label='About', underline=0,
                             command=self.about)
        helpmenu.add_command(label='Instructions', underline=0,
                             command=self.help, accelerator='F1')
        menubar.add_cascade(label='Help', underline=0, menu=helpmenu)

        parent.config(menu=menubar)

    def _init_feedback(self, parent):
        self._feedbackframe = feedbackframe = Frame(parent)
        feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3)
        self._lastoper_label = Label(feedbackframe, text='Last Operation:',
                                     font=self._font)
        self._lastoper_label.pack(side='left')
        lastoperframe = Frame(feedbackframe, relief='sunken', border=1)
        lastoperframe.pack(fill='x', side='right', expand=1, padx=5)
        self._lastoper1 = Label(lastoperframe, foreground='#007070',
                                background='#f0f0f0', font=self._font)
        self._lastoper2 = Label(lastoperframe, anchor='w', width=30,
                                foreground='#004040', background='#f0f0f0',
                                font=self._font)
        self._lastoper1.pack(side='left')
        self._lastoper2.pack(side='left', fill='x', expand=1)

    def _init_canvas(self, parent):
        self._cframe = CanvasFrame(parent, background='white',
                                   width=525, closeenough=10,
                                   border=2, relief='sunken')
        self._cframe.pack(expand=1, fill='both', side='top', pady=2)
        canvas = self._canvas = self._cframe.canvas()

        self._stackwidgets = []
        self._rtextwidgets = []
        self._titlebar = canvas.create_rectangle(0,0,0,0, fill='#c0f0f0',
                                                 outline='black')
        self._exprline = canvas.create_line(0,0,0,0, dash='.')
        self._stacktop = canvas.create_line(0,0,0,0, fill='#408080')
        size = self._size.get()+4
        self._stacklabel = TextWidget(canvas, 'Stack', color='#004040',
                                      font=self._boldfont)
        self._rtextlabel = TextWidget(canvas, 'Remaining Text',
                                      color='#004040', font=self._boldfont)
        self._cframe.add_widget(self._stacklabel)
        self._cframe.add_widget(self._rtextlabel)

    #########################################
    ##  Main draw procedure
    #########################################

    def _redraw(self):
        scrollregion = self._canvas['scrollregion'].split()
        (cx1, cy1, cx2, cy2) = [int(c) for c in scrollregion]

        # Delete the old stack & rtext widgets.
        for stackwidget in self._stackwidgets:
            self._cframe.destroy_widget(stackwidget)
        self._stackwidgets = []
        for rtextwidget in self._rtextwidgets:
            self._cframe.destroy_widget(rtextwidget)
        self._rtextwidgets = []

        # Position the titlebar & exprline
        (x1, y1, x2, y2) = self._stacklabel.bbox()
        y = y2-y1+10
        self._canvas.coords(self._titlebar, -5000, 0, 5000, y-4)
        self._canvas.coords(self._exprline, 0, y*2-10, 5000, y*2-10)

        # Position the titlebar labels..
        (x1, y1, x2, y2) = self._stacklabel.bbox()
        self._stacklabel.move(5-x1, 3-y1)
        (x1, y1, x2, y2) = self._rtextlabel.bbox()
        self._rtextlabel.move(cx2-x2-5, 3-y1)

        # Draw the stack.
        stackx = 5
        for tok in self._parser.stack():
            if isinstance(tok, Tree):
                attribs = {'tree_color': '#4080a0', 'tree_width': 2,
                           'node_font': self._boldfont,
                           'node_color': '#006060',
                           'leaf_color': '#006060', 'leaf_font':self._font}
                widget = tree_to_treesegment(self._canvas, tok,
                                             **attribs)
                widget.label()['color'] = '#000000'
            else:
                widget = TextWidget(self._canvas, tok,
                                    color='#000000', font=self._font)
            widget.bind_click(self._popup_reduce)
            self._stackwidgets.append(widget)
            self._cframe.add_widget(widget, stackx, y)
            stackx = widget.bbox()[2] + 10

        # Draw the remaining text.
        rtextwidth = 0
        for tok in self._parser.remaining_text():
            widget = TextWidget(self._canvas, tok,
                                color='#000000', font=self._font)
            self._rtextwidgets.append(widget)
            self._cframe.add_widget(widget, rtextwidth, y)
            rtextwidth = widget.bbox()[2] + 4

        # Allow enough room to shift the next token (for animations)
        if len(self._rtextwidgets) > 0:
            stackx += self._rtextwidgets[0].width()

        # Move the remaining text to the correct location (keep it
        # right-justified, when possible); and move the remaining text
        # label, if necessary.
        stackx = max(stackx, self._stacklabel.width()+25)
        rlabelwidth = self._rtextlabel.width()+10
        if stackx >= cx2-max(rtextwidth, rlabelwidth):
            cx2 = stackx + max(rtextwidth, rlabelwidth)
        for rtextwidget in self._rtextwidgets:
            rtextwidget.move(4+cx2-rtextwidth, 0)
        self._rtextlabel.move(cx2-self._rtextlabel.bbox()[2]-5, 0)

        midx = (stackx + cx2-max(rtextwidth, rlabelwidth))/2
        self._canvas.coords(self._stacktop, midx, 0, midx, 5000)
        (x1, y1, x2, y2) = self._stacklabel.bbox()

        # Set up binding to allow them to shift a token by dragging it.
        if len(self._rtextwidgets) > 0:
            def drag_shift(widget, midx=midx, self=self):
                if widget.bbox()[0] < midx: self.shift()
                else: self._redraw()
            self._rtextwidgets[0].bind_drag(drag_shift)
            self._rtextwidgets[0].bind_click(self.shift)

        # Draw the stack top.
        self._highlight_productions()

    def _draw_stack_top(self, widget):
        # hack..
        midx = widget.bbox()[2]+50
        self._canvas.coords(self._stacktop, midx, 0, midx, 5000)

    def _highlight_productions(self):
        # Highlight the productions that can be reduced.
        self._prodlist.selection_clear(0, 'end')
        for prod in self._parser.reducible_productions():
            index = self._productions.index(prod)
            self._prodlist.selection_set(index)

    #########################################
    ##  Button Callbacks
    #########################################

    def destroy(self, *e):
        if self._top is None: return
        self._top.destroy()
        self._top = None

    def reset(self, *e):
        self._parser.initialize(self._sent)
        self._lastoper1['text'] = 'Reset App'
        self._lastoper2['text'] = ''
        self._redraw()

    def step(self, *e):
        if self.reduce(): return True
        elif self.shift(): return True
        else:
            if list(self._parser.parses()):
                self._lastoper1['text'] = 'Finished:'
                self._lastoper2['text'] = 'Success'
            else:
                self._lastoper1['text'] = 'Finished:'
                self._lastoper2['text'] = 'Failure'

    def shift(self, *e):
        if self._animating_lock: return
        if self._parser.shift():
            tok = self._parser.stack()[-1]
            self._lastoper1['text'] = 'Shift:'
            self._lastoper2['text'] = '%r' % tok
            if self._animate.get():
                self._animate_shift()
            else:
                self._redraw()
            return True
        return False

    def reduce(self, *e):
        if self._animating_lock: return
        production = self._parser.reduce()
        if production:
            self._lastoper1['text'] = 'Reduce:'
            self._lastoper2['text'] = '%s' % production
            if self._animate.get():
                self._animate_reduce()
            else:
                self._redraw()
        return production

    def undo(self, *e):
        if self._animating_lock: return
        if self._parser.undo():
            self._redraw()

    def postscript(self, *e):
        self._cframe.print_to_file()

    def mainloop(self, *args, **kwargs):
        """
        Enter the Tkinter mainloop.  This function must be called if
        this demo is created from a non-interactive program (e.g.
        from a secript); otherwise, the demo will close as soon as
        the script completes.
        """
        if in_idle(): return
        self._top.mainloop(*args, **kwargs)

    #########################################
    ##  Menubar callbacks
    #########################################

    def resize(self, size=None):
        if size is not None: self._size.set(size)
        size = self._size.get()
        self._font.configure(size=-(abs(size)))
        self._boldfont.configure(size=-(abs(size)))
        self._sysfont.configure(size=-(abs(size)))

        #self._stacklabel['font'] = ('helvetica', -size-4, 'bold')
        #self._rtextlabel['font'] = ('helvetica', -size-4, 'bold')
        #self._lastoper_label['font'] = ('helvetica', -size)
        #self._lastoper1['font'] = ('helvetica', -size)
        #self._lastoper2['font'] = ('helvetica', -size)
        #self._prodlist['font'] = ('helvetica', -size)
        #self._prodlist_label['font'] = ('helvetica', -size-2, 'bold')
        self._redraw()

    def help(self, *e):
        # The default font's not very legible; try using 'fixed' instead.
        try:
            ShowText(self._top, 'Help: Shift-Reduce Parser Application',
                     (__doc__ or '').strip(), width=75, font='fixed')
        except:
            ShowText(self._top, 'Help: Shift-Reduce Parser Application',
                     (__doc__ or '').strip(), width=75)

    def about(self, *e):
        ABOUT = ("NLTK Shift-Reduce Parser Application\n"+
                 "Written by Edward Loper")
        TITLE = 'About: Shift-Reduce Parser Application'
        try:
            from tkinter.messagebox import Message
            Message(message=ABOUT, title=TITLE).show()
        except:
            ShowText(self._top, TITLE, ABOUT)

    def edit_grammar(self, *e):
        CFGEditor(self._top, self._parser.grammar(), self.set_grammar)

    def set_grammar(self, grammar):
        self._parser.set_grammar(grammar)
        self._productions = list(grammar.productions())
        self._prodlist.delete(0, 'end')
        for production in self._productions:
            self._prodlist.insert('end', (' %s' % production))

    def edit_sentence(self, *e):
        sentence = " ".join(self._sent)
        title = 'Edit Text'
        instr = 'Enter a new sentence to parse.'
        EntryDialog(self._top, sentence, instr, self.set_sentence, title)

    def set_sentence(self, sent):
        self._sent = sent.split() #[XX] use tagged?
        self.reset()

    #########################################
    ##  Reduce Production Selection
    #########################################

    def _toggle_grammar(self, *e):
        if self._show_grammar.get():
            self._prodframe.pack(fill='both', side='left', padx=2,
                                 after=self._feedbackframe)
            self._lastoper1['text'] = 'Show Grammar'
        else:
            self._prodframe.pack_forget()
            self._lastoper1['text'] = 'Hide Grammar'
        self._lastoper2['text'] = ''

    def _prodlist_select(self, event):
        selection = self._prodlist.curselection()
        if len(selection) != 1: return
        index = int(selection[0])
        production = self._parser.reduce(self._productions[index])
        if production:
            self._lastoper1['text'] = 'Reduce:'
            self._lastoper2['text'] = '%s' % production
            if self._animate.get():
                self._animate_reduce()
            else:
                self._redraw()
        else:
            # Reset the production selections.
            self._prodlist.selection_clear(0, 'end')
            for prod in self._parser.reducible_productions():
                index = self._productions.index(prod)
                self._prodlist.selection_set(index)

    def _popup_reduce(self, widget):
        # Remove old commands.
        productions = self._parser.reducible_productions()
        if len(productions) == 0: return

        self._reduce_menu.delete(0, 'end')
        for production in productions:
            self._reduce_menu.add_command(label=str(production),
                                          command=self.reduce)
        self._reduce_menu.post(self._canvas.winfo_pointerx(),
                               self._canvas.winfo_pointery())

    #########################################
    ##  Animations
    #########################################

    def _animate_shift(self):
        # What widget are we shifting?
        widget = self._rtextwidgets[0]

        # Where are we shifting from & to?
        right = widget.bbox()[0]
        if len(self._stackwidgets) == 0: left = 5
        else: left = self._stackwidgets[-1].bbox()[2]+10

        # Start animating.
        dt = self._animate.get()
        dx = (left-right)*1.0/dt
        self._animate_shift_frame(dt, widget, dx)

    def _animate_shift_frame(self, frame, widget, dx):
        if frame > 0:
            self._animating_lock = 1
            widget.move(dx, 0)
            self._top.after(10, self._animate_shift_frame,
                            frame-1, widget, dx)
        else:
            # but: stacktop??

            # Shift the widget to the stack.
            del self._rtextwidgets[0]
            self._stackwidgets.append(widget)
            self._animating_lock = 0

            # Display the available productions.
            self._draw_stack_top(widget)
            self._highlight_productions()

    def _animate_reduce(self):
        # What widgets are we shifting?
        numwidgets = len(self._parser.stack()[-1]) # number of children
        widgets = self._stackwidgets[-numwidgets:]

        # How far are we moving?
        if isinstance(widgets[0], TreeSegmentWidget):
            ydist = 15 + widgets[0].label().height()
        else:
            ydist = 15 + widgets[0].height()

        # Start animating.
        dt = self._animate.get()
        dy = ydist*2.0/dt
        self._animate_reduce_frame(dt/2, widgets, dy)

    def _animate_reduce_frame(self, frame, widgets, dy):
        if frame > 0:
            self._animating_lock = 1
            for widget in widgets: widget.move(0, dy)
            self._top.after(10, self._animate_reduce_frame,
                            frame-1, widgets, dy)
        else:
            del self._stackwidgets[-len(widgets):]
            for widget in widgets:
                self._cframe.remove_widget(widget)
            tok = self._parser.stack()[-1]
            if not isinstance(tok, Tree): raise ValueError()
            label = TextWidget(self._canvas, str(tok.label()), color='#006060',
                               font=self._boldfont)
            widget = TreeSegmentWidget(self._canvas, label, widgets,
                                       width=2)
            (x1, y1, x2, y2) = self._stacklabel.bbox()
            y = y2-y1+10
            if not self._stackwidgets: x = 5
            else: x = self._stackwidgets[-1].bbox()[2] + 10
            self._cframe.add_widget(widget, x, y)
            self._stackwidgets.append(widget)

            # Display the available productions.
            self._draw_stack_top(widget)
            self._highlight_productions()

#             # Delete the old widgets..
#             del self._stackwidgets[-len(widgets):]
#             for widget in widgets:
#                 self._cframe.destroy_widget(widget)
#
#             # Make a new one.
#             tok = self._parser.stack()[-1]
#             if isinstance(tok, Tree):
#                 attribs = {'tree_color': '#4080a0', 'tree_width': 2,
#                            'node_font': bold, 'node_color': '#006060',
#                            'leaf_color': '#006060', 'leaf_font':self._font}
#                 widget = tree_to_treesegment(self._canvas, tok.type(),
#                                              **attribs)
#                 widget.node()['color'] = '#000000'
#             else:
#                 widget = TextWidget(self._canvas, tok.type(),
#                                     color='#000000', font=self._font)
#             widget.bind_click(self._popup_reduce)
#             (x1, y1, x2, y2) = self._stacklabel.bbox()
#             y = y2-y1+10
#             if not self._stackwidgets: x = 5
#             else: x = self._stackwidgets[-1].bbox()[2] + 10
#             self._cframe.add_widget(widget, x, y)
#             self._stackwidgets.append(widget)

            #self._redraw()
            self._animating_lock = 0

    #########################################
    ##  Hovering.
    #########################################

    def _highlight_hover(self, event):
        # What production are we hovering over?
        index = self._prodlist.nearest(event.y)
        if self._hover == index: return

        # Clear any previous hover highlighting.
        self._clear_hover()

        # If the production corresponds to an available reduction,
        # highlight the stack.
        selection = [int(s) for s in self._prodlist.curselection()]
        if index in selection:
            rhslen = len(self._productions[index].rhs())
            for stackwidget in self._stackwidgets[-rhslen:]:
                if isinstance(stackwidget, TreeSegmentWidget):
                    stackwidget.label()['color'] = '#00a000'
                else:
                    stackwidget['color'] = '#00a000'

        # Remember what production we're hovering over.
        self._hover = index

    def _clear_hover(self, *event):
        # Clear any previous hover highlighting.
        if self._hover == -1: return
        self._hover = -1
        for stackwidget in self._stackwidgets:
            if isinstance(stackwidget, TreeSegmentWidget):
                stackwidget.label()['color'] = 'black'
            else:
                stackwidget['color'] = 'black'
def demo():
    """
    A demonstration of the probabilistic parsers.  The user is
    prompted to select which demo to run, and how many parses should
    be found; and then each parser is run on the same demo, and a
    summary of the results are displayed.
    """
    import sys, time
    from nltk import tokenize
    from nltk.parse import ViterbiParser
    from nltk.grammar import toy_pcfg1, toy_pcfg2
    from nltk.draw.tree import draw_trees
    from nltk import Tree
    from nltk.draw.util import CanvasFrame
    from nltk.draw import TreeWidget

    # Define two demos.  Each demo has a sentence and a grammar.
    # demos = [('move the green sphere to the bottom left corner', learned_pcfg),
    #          ('move the green ball over the red block', learned_pcfg),
    #          ('take the green pyramid and put it in the top left corner', learned_pcfg),
    #           ('put the green pyramid on the red block', learned_pcfg),
    #           ('move the red cylinder and place it on top of the blue cylinder that is on top of a green cylinder', learned_pcfg),]

    # Ask the user which demo they want to use.
    # print()
    # for i in range(len(demos)):
    #     print('%3s: %s' % (i+1, demos[i][0]))
    #     print('     %r' % demos[i][1])
    #     print()
    # print('Which demo (%d-%d)? ' % (1, len(demos)), end=' ')
    # try:
    #     snum = int(sys.stdin.readline().strip())-1
    #     sent, grammar = demos[snum]
    # except:
    #     print('Bad sentence number')
    #     return

    max_scene = 1

    if max_scene<10:            sc = '0000'+str(max_scene)
    elif max_scene<100:         sc = '000'+str(max_scene)
    elif max_scene<1000:        sc = '00'+str(max_scene)
    elif max_scene<10000:       sc = '0'+str(max_scene)

    g = 'grammar_'+sc+'.txt'
    learned_pcfg = load('/home/omari/Dropbox/robot_modified/AR/grammar/'+g)
    grammar = learned_pcfg

    file1 = open('/home/omari/Dropbox/robot_modified/AR/hypotheses/matched_commands.txt', 'r')
    g1 = [i for i in file1.readlines()]
    for line in g1:
        line = unicode(line,encoding='utf-8')
        sent = line.split('\n')[0].split('-')[-1]
        scene = line.split('\n')[0].split('-')[0]
        sent_num = line.split('\n')[0].split('-')[1]
        print(line)
        if scene == '239' and sent_num == '0':  continue


        # Tokenize the sentence.
        tokens = sent.split()

        parser = ViterbiParser(grammar)
        all_parses = {}

        # print('\nsent: %s\nparser: %s\ngrammar: %s' % (sent,parser,grammar))
        parser.trace(3)
        parses = parser.parse_all(tokens)
        average = (reduce(lambda a,b:a+b.prob(), parses, 0)/len(parses)
                   if parses else 0)
        num_parses = len(parses)
        for p in parses:
            all_parses[p.freeze()] = 1

        # Print some summary statistics
        # print()
        # print('Time (secs)   # Parses   Average P(parse)')
        # print('-----------------------------------------')
        # print('%11.4f%11d%19.14f' % (time, num_parses, average))
        parses = all_parses.keys()
        if parses:
            p = reduce(lambda a,b:a+b.prob(), parses, 0)/len(parses)
        else: p = 0
        # print('------------------------------------------')
        # print('%11s%11d%19.14f' % ('n/a', len(parses), p))

        # Ask the user if we should draw the parses.
        # print()
        # print('Draw parses (y/n)? ', end=' ')
        # if sys.stdin.readline().strip().lower().startswith('y'):

        #     print('  please wait...')
        # draw_trees(*parses)

        cf = CanvasFrame()
        # t = Tree(parses)
        t = Tree.fromstring('(S  (CH_POS_PREPOST move)  (PRE_POST    (PRE      (the the)      (_entity (F_HSV green) (F_SHAPE sphere)))    (PREPOST_connect (to to) (the the))    (POST      (_F_POS (F_POS (_bottom_left (bottom bottom) (left left)))) (corner corner))))')

        tc = TreeWidget(cf.canvas(), t, draggable=1,
                        node_font=('helvetica', -14),
                        leaf_font=('helvetica', -12),
                        roof_fill='white', roof_color='black',
                        leaf_color='green4', node_color='blue4')
        cf.add_widget(tc,10,10)

        # tc = TreeWidget(cf.canvas(),t)
        # cf.add_widget(tc,10,10) # (10,10) offsets
        cf.print_to_file('/home/omari/Dropbox/robot_modified/trees/scene-'+scene+'-'+sent_num+'.ps')
        cf.destroy()
Example #41
0
class DrtGlueDemo(object):
    def __init__(self, examples):
        # Set up the main window.
        self._top = Tk()
        self._top.title('DRT Glue Demo')

        # Set up key bindings.
        self._init_bindings()

        # Initialize the fonts.self._error = None
        self._init_fonts(self._top)

        self._examples = examples
        self._readingCache = [None for example in examples]

        # The user can hide the grammar.
        self._show_grammar = IntVar(self._top)
        self._show_grammar.set(1)

        # Set the data to None
        self._curExample = -1
        self._readings = []
        self._drs = None
        self._drsWidget = None
        self._error = None

        self._init_glue()

        # Create the basic frames.
        self._init_menubar(self._top)
        self._init_buttons(self._top)
        self._init_exampleListbox(self._top)
        self._init_readingListbox(self._top)
        self._init_canvas(self._top)

        # Resize callback
        self._canvas.bind('<Configure>', self._configure)

    #########################################
    ##  Initialization Helpers
    #########################################

    def _init_glue(self):
        tagger = RegexpTagger(
            [('^(David|Mary|John)$', 'NNP'),
             ('^(walks|sees|eats|chases|believes|gives|sleeps|chases|persuades|tries|seems|leaves)$', 'VB'),
             ('^(go|order|vanish|find|approach)$', 'VB'),
             ('^(a)$', 'ex_quant'),
             ('^(every)$', 'univ_quant'),
             ('^(sandwich|man|dog|pizza|unicorn|cat|senator)$', 'NN'),
             ('^(big|gray|former)$', 'JJ'),
             ('^(him|himself)$', 'PRP')
        ])

        depparser = MaltParser(tagger=tagger)
        self._glue = DrtGlue(depparser=depparser, remove_duplicates=False)

    def _init_fonts(self, root):
        # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html>
        self._sysfont = Font(font=Button()["font"])
        root.option_add("*Font", self._sysfont)

        # TWhat's our font size (default=same as sysfont)
        self._size = IntVar(root)
        self._size.set(self._sysfont.cget('size'))

        self._boldfont = Font(family='helvetica', weight='bold',
                                    size=self._size.get())
        self._font = Font(family='helvetica',
                                    size=self._size.get())
        if self._size.get() < 0: big = self._size.get()-2
        else: big = self._size.get()+2
        self._bigfont = Font(family='helvetica', weight='bold',
                                    size=big)

    def _init_exampleListbox(self, parent):
        self._exampleFrame = listframe = Frame(parent)
        self._exampleFrame.pack(fill='both', side='left', padx=2)
        self._exampleList_label = Label(self._exampleFrame, font=self._boldfont,
                                     text='Examples')
        self._exampleList_label.pack()
        self._exampleList = Listbox(self._exampleFrame, selectmode='single',
                                 relief='groove', background='white',
                                 foreground='#909090', font=self._font,
                                 selectforeground='#004040',
                                 selectbackground='#c0f0c0')

        self._exampleList.pack(side='right', fill='both', expand=1)

        for example in self._examples:
            self._exampleList.insert('end', ('  %s' % example))
        self._exampleList.config(height=min(len(self._examples), 25), width=40)

        # Add a scrollbar if there are more than 25 examples.
        if len(self._examples) > 25:
            listscroll = Scrollbar(self._exampleFrame,
                                   orient='vertical')
            self._exampleList.config(yscrollcommand = listscroll.set)
            listscroll.config(command=self._exampleList.yview)
            listscroll.pack(side='left', fill='y')

        # If they select a example, apply it.
        self._exampleList.bind('<<ListboxSelect>>', self._exampleList_select)

    def _init_readingListbox(self, parent):
        self._readingFrame = listframe = Frame(parent)
        self._readingFrame.pack(fill='both', side='left', padx=2)
        self._readingList_label = Label(self._readingFrame, font=self._boldfont,
                                     text='Readings')
        self._readingList_label.pack()
        self._readingList = Listbox(self._readingFrame, selectmode='single',
                                 relief='groove', background='white',
                                 foreground='#909090', font=self._font,
                                 selectforeground='#004040',
                                 selectbackground='#c0f0c0')

        self._readingList.pack(side='right', fill='both', expand=1)

        # Add a scrollbar if there are more than 25 examples.
        listscroll = Scrollbar(self._readingFrame,
                               orient='vertical')
        self._readingList.config(yscrollcommand = listscroll.set)
        listscroll.config(command=self._readingList.yview)
        listscroll.pack(side='right', fill='y')

        self._populate_readingListbox()

    def _populate_readingListbox(self):
        # Populate the listbox with integers
        self._readingList.delete(0, 'end')
        for i in range(len(self._readings)):
            self._readingList.insert('end', ('  %s' % (i+1)))
        self._readingList.config(height=min(len(self._readings), 25), width=5)

        # If they select a example, apply it.
        self._readingList.bind('<<ListboxSelect>>', self._readingList_select)

    def _init_bindings(self):
        # Key bindings are a good thing.
        self._top.bind('<Control-q>', self.destroy)
        self._top.bind('<Control-x>', self.destroy)
        self._top.bind('<Escape>', self.destroy)
        self._top.bind('n', self.next)
        self._top.bind('<space>', self.next)
        self._top.bind('p', self.prev)
        self._top.bind('<BackSpace>', self.prev)

    def _init_buttons(self, parent):
        # Set up the frames.
        self._buttonframe = buttonframe = Frame(parent)
        buttonframe.pack(fill='none', side='bottom', padx=3, pady=2)
        Button(buttonframe, text='Prev',
               background='#90c0d0', foreground='black',
               command=self.prev,).pack(side='left')
        Button(buttonframe, text='Next',
               background='#90c0d0', foreground='black',
               command=self.next,).pack(side='left')

    def _configure(self, event):
        self._autostep = 0
        (x1, y1, x2, y2) = self._cframe.scrollregion()
        y2 = event.height - 6
        self._canvas['scrollregion'] = '%d %d %d %d' % (x1,y1,x2,y2)
        self._redraw()

    def _init_canvas(self, parent):
        self._cframe = CanvasFrame(parent, background='white',
                                   #width=525, height=250,
                                   closeenough=10,
                                   border=2, relief='sunken')
        self._cframe.pack(expand=1, fill='both', side='top', pady=2)
        canvas = self._canvas = self._cframe.canvas()

        # Initially, there's no tree or text
        self._tree = None
        self._textwidgets = []
        self._textline = None

    def _init_menubar(self, parent):
        menubar = Menu(parent)

        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label='Exit', underline=1,
                             command=self.destroy, accelerator='q')
        menubar.add_cascade(label='File', underline=0, menu=filemenu)

        actionmenu = Menu(menubar, tearoff=0)
        actionmenu.add_command(label='Next', underline=0,
                               command=self.next, accelerator='n, Space')
        actionmenu.add_command(label='Previous', underline=0,
                               command=self.prev, accelerator='p, Backspace')
        menubar.add_cascade(label='Action', underline=0, menu=actionmenu)

        optionmenu = Menu(menubar, tearoff=0)
        optionmenu.add_checkbutton(label='Remove Duplicates', underline=0,
                                   variable=self._glue.remove_duplicates,
                                   command=self._toggle_remove_duplicates,
                                   accelerator='r')
        menubar.add_cascade(label='Options', underline=0, menu=optionmenu)

        viewmenu = Menu(menubar, tearoff=0)
        viewmenu.add_radiobutton(label='Tiny', variable=self._size,
                                 underline=0, value=10, command=self.resize)
        viewmenu.add_radiobutton(label='Small', variable=self._size,
                                 underline=0, value=12, command=self.resize)
        viewmenu.add_radiobutton(label='Medium', variable=self._size,
                                 underline=0, value=14, command=self.resize)
        viewmenu.add_radiobutton(label='Large', variable=self._size,
                                 underline=0, value=18, command=self.resize)
        viewmenu.add_radiobutton(label='Huge', variable=self._size,
                                 underline=0, value=24, command=self.resize)
        menubar.add_cascade(label='View', underline=0, menu=viewmenu)

        helpmenu = Menu(menubar, tearoff=0)
        helpmenu.add_command(label='About', underline=0,
                             command=self.about)
        menubar.add_cascade(label='Help', underline=0, menu=helpmenu)

        parent.config(menu=menubar)

    #########################################
    ##  Main draw procedure
    #########################################

    def _redraw(self):
        canvas = self._canvas

        # Delete the old DRS, widgets, etc.
        if self._drsWidget is not None:
            self._drsWidget.clear()

        if self._drs:
            self._drsWidget = DrsWidget( self._canvas, self._drs )
            self._drsWidget.draw()

        if self._error:
            self._drsWidget = DrsWidget( self._canvas, self._error )
            self._drsWidget.draw()

    #########################################
    ##  Button Callbacks
    #########################################

    def destroy(self, *e):
        self._autostep = 0
        if self._top is None: return
        self._top.destroy()
        self._top = None

    def prev(self, *e):
        selection = self._readingList.curselection()
        readingListSize = self._readingList.size()

        # there are readings
        if readingListSize > 0:
            # if one reading is currently selected
            if len(selection) == 1:
                index = int(selection[0])

                # if it's on (or before) the first item
                if index <= 0:
                    self._select_previous_example()
                else:
                    self._readingList_store_selection(index-1)

            else:
                #select its first reading
                self._readingList_store_selection(readingListSize-1)

        else:
            self._select_previous_example()


    def _select_previous_example(self):
        #if the current example is not the first example
        if self._curExample > 0:
            self._exampleList_store_selection(self._curExample-1)
        else:
            #go to the last example
            self._exampleList_store_selection(len(self._examples)-1)

    def next(self, *e):
        selection = self._readingList.curselection()
        readingListSize = self._readingList.size()

        # if there are readings
        if readingListSize > 0:
            # if one reading is currently selected
            if len(selection) == 1:
                index = int(selection[0])

                # if it's on (or past) the last item
                if index >= (readingListSize-1):
                    self._select_next_example()
                else:
                    self._readingList_store_selection(index+1)

            else:
                #select its first reading
                self._readingList_store_selection(0)

        else:
            self._select_next_example()

    def _select_next_example(self):
        #if the current example is not the last example
        if self._curExample < len(self._examples)-1:
            self._exampleList_store_selection(self._curExample+1)
        else:
            #go to the first example
            self._exampleList_store_selection(0)


    def about(self, *e):
        ABOUT = ("NLTK Discourse Representation Theory (DRT) Glue Semantics Demo\n"+
                 "Written by Daniel H. Garrette")
        TITLE = 'About: NLTK DRT Glue Demo'
        try:
            from tkMessageBox import Message
            Message(message=ABOUT, title=TITLE).show()
        except:
            ShowText(self._top, TITLE, ABOUT)

    def postscript(self, *e):
        self._autostep = 0
        self._cframe.print_to_file()

    def mainloop(self, *args, **kwargs):
        """
        Enter the Tkinter mainloop.  This function must be called if
        this demo is created from a non-interactive program (e.g.
        from a secript); otherwise, the demo will close as soon as
        the script completes.
        """
        if in_idle(): return
        self._top.mainloop(*args, **kwargs)

    def resize(self, size=None):
        if size is not None: self._size.set(size)
        size = self._size.get()
        self._font.configure(size=-(abs(size)))
        self._boldfont.configure(size=-(abs(size)))
        self._sysfont.configure(size=-(abs(size)))
        self._bigfont.configure(size=-(abs(size+2)))
        self._redraw()

    def _toggle_remove_duplicates(self):
        self._glue.remove_duplicates = not self._glue.remove_duplicates

        self._exampleList.selection_clear(0, 'end')
        self._readings = []
        self._populate_readingListbox()
        self._readingCache = [None for ex in self._examples]
        self._curExample = -1
        self._error = None

        self._drs = None
        self._redraw()


    def _exampleList_select(self, event):
        selection = self._exampleList.curselection()
        if len(selection) != 1: return
        self._exampleList_store_selection(int(selection[0]))

    def _exampleList_store_selection(self, index):
        self._curExample = index
        example = self._examples[index]

        self._exampleList.selection_clear(0, 'end')
        if example:
            cache = self._readingCache[index]
            if cache:
                if isinstance(cache, list):
                    self._readings = cache
                    self._error = None
                else:
                    self._readings = []
                    self._error = cache
            else:
                try:
                    self._readings = self._glue.parse_to_meaning(example)
                    self._error = None
                    self._readingCache[index] = self._readings
                except Exception, e:
                    self._readings = []
                    self._error = DrtVariableExpression(Variable('Error: ' + str(e)))
                    self._readingCache[index] = self._error

                    #add a star to the end of the example
                    self._exampleList.delete(index)
                    self._exampleList.insert(index, ('  %s *' % example))
                    self._exampleList.config(height=min(len(self._examples), 25), width=40)

            self._populate_readingListbox()

            self._exampleList.selection_set(index)

            self._drs = None
            self._redraw()
		print(str(e))
#	for subtree in namedEnt.subtrees(filter = lambda t: t.label() == 'Chunk'):
#		print(subtree)	
'''
def extract_entity_names(t):
	entity_names = []
	if hasattr(t, 'node') and t.node:
		if t.node == 'NE':
			entity_names.append(' '.join([child[0] for child in t]))
		else:
			for child in t:
				entity_names.extend(extract_entity_names(child)) 
	return entity_names

'''
from nltk import Tree
from nltk.draw.util import CanvasFrame
from nltk.draw import TreeWidget

cf = CanvasFrame()
t = Tree.fromstring('(S (NE this tree))')
tc = TreeWidget(cf.canvas(),t)
cf.add_widget(tc,10,10) # (10,10) offsets
cf.print_to_file('tree.ps')
cf.destroy()



process_content()

{<NOUN><IN><ADJ><NOUN>}
{<ADJ><NOUN><IN><NOUN>}
{<NOUN><IN><NOUN>} # 名词+介词+名词
ADV_ADJ:{<RB><ADJ>} # 副词+形容词
ADJ_PREP_NOUN:{<ADJ><IN><NOUN>} # 形容词+介词+名词
"""

cp = nltk.RegexpParser(grammar)

if len(sys.argv) < 2:
    sys.exit(0)

for s in sys.argv[1:]:
    print('*****************************')
    print(s)
    tags = nltk.pos_tag(nltk.word_tokenize(s))
    tree = nltk.chunk.ne_chunk(tags)
    print(str(tree))
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), tree)
    cf.add_widget(tc, 10, 10)
    cf.print_to_file(s+'.1.ps')
    cf.destroy()
    tree = cp.parse(tags)

    print(str(tree))
    cf = CanvasFrame()
    tc = TreeWidget(cf.canvas(), tree)
    cf.add_widget(tc, 10, 10)
    cf.print_to_file(s+'.2.ps')
Example #44
0
    low = sys.argv[1].lower()
    # then chop off the punctuation
    # http://stackoverflow.com/questions/16050952/how-to-remove-all-the-punctuation-in-a-string-python
    lower = "".join(c for c in low if c not in ('!', '.', '?'))
    # generate the parse tree for the sentence they inputed
    trees = generate_parse_tree(lower, get_grammar(sys.argv[2]))
    # print type(trees)
    numTrees = 0
    for tree in trees:
        if numTrees >= MAX_TREES:
            break
        # if the tree is an error tree, continue to the next one
        # print tree
        if tree == "Error":
            continue
        # print "tree using grammar " + ": "
        # draw_trees(tree)
        # http://stackoverflow.com/questions/23429117/saving-nltk-drawn-parse-tree-to-image-file
        cf = CanvasFrame()
        tc = TreeWidget(cf.canvas(), tree)
        cf.add_widget(tc, 10, 10)  # (10,10) offsets
        # compute the filename from the input, then write the image to the file
        filename = 'trees/tree_' + sys.argv[2] + '_' + computeNameFromSentence(lower)
        cf.print_to_file(filename + '.ps')
        # convert the file to PNG
        # http://stackoverflow.com/questions/89228/calling-an-external-command-in-python
        call(["convert", filename + '.ps', filename + '.png'])
        cf.destroy()
        print filename + '.png'
        numTrees += 1
from nltk import Tree
from nltk.draw.util import CanvasFrame
from nltk.draw import TreeWidget

cf = CanvasFrame()
t = Tree('(S  (CH_POS_PREPOST move)  (PRE_POST    (PRE      (the the)      (_entity (F_HSV green) (F_SHAPE sphere)))    (PREPOST_connect (to to) (the the))    (POST      (_F_POS (F_POS (_bottom_left (bottom bottom) (left left)))) (corner corner))))')
tc = TreeWidget(cf.canvas(),t)
cf.add_widget(tc,10,10) # (10,10) offsets
cf.print_to_file('/home/omari/Dropbox/robot_modified/trees/test.ps')
cf.destroy()
Example #46
0
class RecursiveDescentApp(object):
    """
    A graphical tool for exploring the recursive descent parser.  The tool
    displays the parser's tree and the remaining text, and allows the
    user to control the parser's operation.  In particular, the user
    can expand subtrees on the frontier, match tokens on the frontier
    against the text, and backtrack.  A "step" button simply steps
    through the parsing process, performing the operations that
    ``RecursiveDescentParser`` would use.
    """
    def __init__(self, grammar, sent, trace=0):
        self._sent = sent
        self._parser = SteppingRecursiveDescentParser(grammar, trace)

        # Set up the main window.
        self._top = Tk()
        self._top.title('Recursive Descent Parser Application')

        # Set up key bindings.
        self._init_bindings()

        # Initialize the fonts.
        self._init_fonts(self._top)

        # Animations.  animating_lock is a lock to prevent the demo
        # from performing new operations while it's animating.
        self._animation_frames = IntVar(self._top)
        self._animation_frames.set(5)
        self._animating_lock = 0
        self._autostep = 0

        # The user can hide the grammar.
        self._show_grammar = IntVar(self._top)
        self._show_grammar.set(1)

        # Create the basic frames.
        self._init_menubar(self._top)
        self._init_buttons(self._top)
        self._init_feedback(self._top)
        self._init_grammar(self._top)
        self._init_canvas(self._top)

        # Initialize the parser.
        self._parser.initialize(self._sent)

        # Resize callback
        self._canvas.bind('<Configure>', self._configure)

    #########################################
    ##  Initialization Helpers
    #########################################

    def _init_fonts(self, root):
        # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html>
        self._sysfont = tkFont.Font(font=Button()["font"])
        root.option_add("*Font", self._sysfont)

        # TWhat's our font size (default=same as sysfont)
        self._size = IntVar(root)
        self._size.set(self._sysfont.cget('size'))

        self._boldfont = tkFont.Font(family='helvetica', weight='bold',
                                    size=self._size.get())
        self._font = tkFont.Font(family='helvetica',
                                    size=self._size.get())
        if self._size.get() < 0: big = self._size.get()-2
        else: big = self._size.get()+2
        self._bigfont = tkFont.Font(family='helvetica', weight='bold',
                                    size=big)

    def _init_grammar(self, parent):
        # Grammar view.
        self._prodframe = listframe = Frame(parent)
        self._prodframe.pack(fill='both', side='left', padx=2)
        self._prodlist_label = Label(self._prodframe, font=self._boldfont,
                                     text='Available Expansions')
        self._prodlist_label.pack()
        self._prodlist = Listbox(self._prodframe, selectmode='single',
                                 relief='groove', background='white',
                                 foreground='#909090', font=self._font,
                                 selectforeground='#004040',
                                 selectbackground='#c0f0c0')

        self._prodlist.pack(side='right', fill='both', expand=1)

        self._productions = list(self._parser.grammar().productions())
        for production in self._productions:
            self._prodlist.insert('end', ('  %s' % production))
        self._prodlist.config(height=min(len(self._productions), 25))

        # Add a scrollbar if there are more than 25 productions.
        if len(self._productions) > 25:
            listscroll = Scrollbar(self._prodframe,
                                   orient='vertical')
            self._prodlist.config(yscrollcommand = listscroll.set)
            listscroll.config(command=self._prodlist.yview)
            listscroll.pack(side='left', fill='y')

        # If they select a production, apply it.
        self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select)

    def _init_bindings(self):
        # Key bindings are a good thing.
        self._top.bind('<Control-q>', self.destroy)
        self._top.bind('<Control-x>', self.destroy)
        self._top.bind('<Escape>', self.destroy)
        self._top.bind('e', self.expand)
        #self._top.bind('<Alt-e>', self.expand)
        #self._top.bind('<Control-e>', self.expand)
        self._top.bind('m', self.match)
        self._top.bind('<Alt-m>', self.match)
        self._top.bind('<Control-m>', self.match)
        self._top.bind('b', self.backtrack)
        self._top.bind('<Alt-b>', self.backtrack)
        self._top.bind('<Control-b>', self.backtrack)
        self._top.bind('<Control-z>', self.backtrack)
        self._top.bind('<BackSpace>', self.backtrack)
        self._top.bind('a', self.autostep)
        #self._top.bind('<Control-a>', self.autostep)
        self._top.bind('<Control-space>', self.autostep)
        self._top.bind('<Control-c>', self.cancel_autostep)
        self._top.bind('<space>', self.step)
        self._top.bind('<Delete>', self.reset)
        self._top.bind('<Control-p>', self.postscript)
        #self._top.bind('<h>', self.help)
        #self._top.bind('<Alt-h>', self.help)
        self._top.bind('<Control-h>', self.help)
        self._top.bind('<F1>', self.help)
        #self._top.bind('<g>', self.toggle_grammar)
        #self._top.bind('<Alt-g>', self.toggle_grammar)
        #self._top.bind('<Control-g>', self.toggle_grammar)
        self._top.bind('<Control-g>', self.edit_grammar)
        self._top.bind('<Control-t>', self.edit_sentence)

    def _init_buttons(self, parent):
        # Set up the frames.
        self._buttonframe = buttonframe = Frame(parent)
        buttonframe.pack(fill='none', side='bottom', padx=3, pady=2)
        Button(buttonframe, text='Step',
               background='#90c0d0', foreground='black',
               command=self.step,).pack(side='left')
        Button(buttonframe, text='Autostep',
               background='#90c0d0', foreground='black',
               command=self.autostep,).pack(side='left')
        Button(buttonframe, text='Expand', underline=0,
               background='#90f090', foreground='black',
               command=self.expand).pack(side='left')
        Button(buttonframe, text='Match', underline=0,
               background='#90f090', foreground='black',
               command=self.match).pack(side='left')
        Button(buttonframe, text='Backtrack', underline=0,
               background='#f0a0a0', foreground='black',
               command=self.backtrack).pack(side='left')
        # Replace autostep...
#         self._autostep_button = Button(buttonframe, text='Autostep',
#                                        underline=0, command=self.autostep)
#         self._autostep_button.pack(side='left')

    def _configure(self, event):
        self._autostep = 0
        (x1, y1, x2, y2) = self._cframe.scrollregion()
        y2 = event.height - 6
        self._canvas['scrollregion'] = '%d %d %d %d' % (x1,y1,x2,y2)
        self._redraw()

    def _init_feedback(self, parent):
        self._feedbackframe = feedbackframe = Frame(parent)
        feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3)
        self._lastoper_label = Label(feedbackframe, text='Last Operation:',
                                     font=self._font)
        self._lastoper_label.pack(side='left')
        lastoperframe = Frame(feedbackframe, relief='sunken', border=1)
        lastoperframe.pack(fill='x', side='right', expand=1, padx=5)
        self._lastoper1 = Label(lastoperframe, foreground='#007070',
                                background='#f0f0f0', font=self._font)
        self._lastoper2 = Label(lastoperframe, anchor='w', width=30,
                                foreground='#004040', background='#f0f0f0',
                                font=self._font)
        self._lastoper1.pack(side='left')
        self._lastoper2.pack(side='left', fill='x', expand=1)

    def _init_canvas(self, parent):
        self._cframe = CanvasFrame(parent, background='white',
                                   #width=525, height=250,
                                   closeenough=10,
                                   border=2, relief='sunken')
        self._cframe.pack(expand=1, fill='both', side='top', pady=2)
        canvas = self._canvas = self._cframe.canvas()

        # Initially, there's no tree or text
        self._tree = None
        self._textwidgets = []
        self._textline = None

    def _init_menubar(self, parent):
        menubar = Menu(parent)

        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label='Reset Parser', underline=0,
                             command=self.reset, accelerator='Del')
        filemenu.add_command(label='Print to Postscript', underline=0,
                             command=self.postscript, accelerator='Ctrl-p')
        filemenu.add_command(label='Exit', underline=1,
                             command=self.destroy, accelerator='Ctrl-x')
        menubar.add_cascade(label='File', underline=0, menu=filemenu)

        editmenu = Menu(menubar, tearoff=0)
        editmenu.add_command(label='Edit Grammar', underline=5,
                             command=self.edit_grammar,
                             accelerator='Ctrl-g')
        editmenu.add_command(label='Edit Text', underline=5,
                             command=self.edit_sentence,
                             accelerator='Ctrl-t')
        menubar.add_cascade(label='Edit', underline=0, menu=editmenu)

        rulemenu = Menu(menubar, tearoff=0)
        rulemenu.add_command(label='Step', underline=1,
                             command=self.step, accelerator='Space')
        rulemenu.add_separator()
        rulemenu.add_command(label='Match', underline=0,
                             command=self.match, accelerator='Ctrl-m')
        rulemenu.add_command(label='Expand', underline=0,
                             command=self.expand, accelerator='Ctrl-e')
        rulemenu.add_separator()
        rulemenu.add_command(label='Backtrack', underline=0,
                             command=self.backtrack, accelerator='Ctrl-b')
        menubar.add_cascade(label='Apply', underline=0, menu=rulemenu)

        viewmenu = Menu(menubar, tearoff=0)
        viewmenu.add_checkbutton(label="Show Grammar", underline=0,
                                 variable=self._show_grammar,
                                 command=self._toggle_grammar)
        viewmenu.add_separator()
        viewmenu.add_radiobutton(label='Tiny', variable=self._size,
                                 underline=0, value=10, command=self.resize)
        viewmenu.add_radiobutton(label='Small', variable=self._size,
                                 underline=0, value=12, command=self.resize)
        viewmenu.add_radiobutton(label='Medium', variable=self._size,
                                 underline=0, value=14, command=self.resize)
        viewmenu.add_radiobutton(label='Large', variable=self._size,
                                 underline=0, value=18, command=self.resize)
        viewmenu.add_radiobutton(label='Huge', variable=self._size,
                                 underline=0, value=24, command=self.resize)
        menubar.add_cascade(label='View', underline=0, menu=viewmenu)

        animatemenu = Menu(menubar, tearoff=0)
        animatemenu.add_radiobutton(label="No Animation", underline=0,
                                    variable=self._animation_frames,
                                    value=0)
        animatemenu.add_radiobutton(label="Slow Animation", underline=0,
                                    variable=self._animation_frames,
                                    value=10, accelerator='-')
        animatemenu.add_radiobutton(label="Normal Animation", underline=0,
                                    variable=self._animation_frames,
                                    value=5, accelerator='=')
        animatemenu.add_radiobutton(label="Fast Animation", underline=0,
                                    variable=self._animation_frames,
                                    value=2, accelerator='+')
        menubar.add_cascade(label="Animate", underline=1, menu=animatemenu)


        helpmenu = Menu(menubar, tearoff=0)
        helpmenu.add_command(label='About', underline=0,
                             command=self.about)
        helpmenu.add_command(label='Instructions', underline=0,
                             command=self.help, accelerator='F1')
        menubar.add_cascade(label='Help', underline=0, menu=helpmenu)

        parent.config(menu=menubar)

    #########################################
    ##  Helper
    #########################################

    def _get(self, widget, treeloc):
        for i in treeloc: widget = widget.subtrees()[i]
        if isinstance(widget, TreeSegmentWidget):
            widget = widget.node()
        return widget

    #########################################
    ##  Main draw procedure
    #########################################

    def _redraw(self):
        canvas = self._canvas

        # Delete the old tree, widgets, etc.
        if self._tree is not None:
            self._cframe.destroy_widget(self._tree)
        for twidget in self._textwidgets:
            self._cframe.destroy_widget(twidget)
        if self._textline is not None:
            self._canvas.delete(self._textline)

        # Draw the tree.
        helv = ('helvetica', -self._size.get())
        bold = ('helvetica', -self._size.get(), 'bold')
        attribs = {'tree_color': '#000000', 'tree_width': 2,
                   'node_font': bold, 'leaf_font': helv,}
        tree = self._parser.tree()
        self._tree = tree_to_treesegment(canvas, tree, **attribs)
        self._cframe.add_widget(self._tree, 30, 5)

        # Draw the text.
        helv = ('helvetica', -self._size.get())
        bottom = y = self._cframe.scrollregion()[3]
        self._textwidgets = [TextWidget(canvas, word, font=self._font)
                             for word in self._sent]
        for twidget in self._textwidgets:
            self._cframe.add_widget(twidget, 0, 0)
            twidget.move(0, bottom-twidget.bbox()[3]-5)
            y = min(y, twidget.bbox()[1])

        # Draw a line over the text, to separate it from the tree.
        self._textline = canvas.create_line(-5000, y-5, 5000, y-5, dash='.')

        # Highlight appropriate nodes.
        self._highlight_nodes()
        self._highlight_prodlist()

        # Make sure the text lines up.
        self._position_text()


    def _redraw_quick(self):
        # This should be more-or-less sufficient after an animation.
        self._highlight_nodes()
        self._highlight_prodlist()
        self._position_text()

    def _highlight_nodes(self):
        # Highlight the list of nodes to be checked.
        bold = ('helvetica', -self._size.get(), 'bold')
        for treeloc in self._parser.frontier()[:1]:
            self._get(self._tree, treeloc)['color'] = '#20a050'
            self._get(self._tree, treeloc)['font'] = bold
        for treeloc in self._parser.frontier()[1:]:
            self._get(self._tree, treeloc)['color'] = '#008080'

    def _highlight_prodlist(self):
        # Highlight the productions that can be expanded.
        # Boy, too bad tkinter doesn't implement Listbox.itemconfig;
        # that would be pretty useful here.
        self._prodlist.delete(0, 'end')
        expandable = self._parser.expandable_productions()
        untried = self._parser.untried_expandable_productions()
        productions = self._productions
        for index in range(len(productions)):
            if productions[index] in expandable:
                if productions[index] in untried:
                    self._prodlist.insert(index, ' %s' % productions[index])
                else:
                    self._prodlist.insert(index, ' %s (TRIED)' %
                                          productions[index])
                self._prodlist.selection_set(index)
            else:
                self._prodlist.insert(index, ' %s' % productions[index])

    def _position_text(self):
        # Line up the text widgets that are matched against the tree
        numwords = len(self._sent)
        num_matched = numwords - len(self._parser.remaining_text())
        leaves = self._tree_leaves()[:num_matched]
        xmax = self._tree.bbox()[0]
        for i in range(0, len(leaves)):
            widget = self._textwidgets[i]
            leaf = leaves[i]
            widget['color'] = '#006040'
            leaf['color'] = '#006040'
            widget.move(leaf.bbox()[0] - widget.bbox()[0], 0)
            xmax = widget.bbox()[2] + 10

        # Line up the text widgets that are not matched against the tree.
        for i in range(len(leaves), numwords):
            widget = self._textwidgets[i]
            widget['color'] = '#a0a0a0'
            widget.move(xmax - widget.bbox()[0], 0)
            xmax = widget.bbox()[2] + 10

        # If we have a complete parse, make everything green :)
        if self._parser.currently_complete():
            for twidget in self._textwidgets:
                twidget['color'] = '#00a000'

        # Move the matched leaves down to the text.
        for i in range(0, len(leaves)):
            widget = self._textwidgets[i]
            leaf = leaves[i]
            dy = widget.bbox()[1] - leaf.bbox()[3] - 10.0
            dy = max(dy, leaf.parent().node().bbox()[3] - leaf.bbox()[3] + 10)
            leaf.move(0, dy)

    def _tree_leaves(self, tree=None):
        if tree is None: tree = self._tree
        if isinstance(tree, TreeSegmentWidget):
            leaves = []
            for child in tree.subtrees(): leaves += self._tree_leaves(child)
            return leaves
        else:
            return [tree]

    #########################################
    ##  Button Callbacks
    #########################################

    def destroy(self, *e):
        self._autostep = 0
        if self._top is None: return
        self._top.destroy()
        self._top = None

    def reset(self, *e):
        self._autostep = 0
        self._parser.initialize(self._sent)
        self._lastoper1['text'] = 'Reset Application'
        self._lastoper2['text'] = ''
        self._redraw()

    def autostep(self, *e):
        if self._animation_frames.get() == 0:
            self._animation_frames.set(2)
        if self._autostep:
            self._autostep = 0
        else:
            self._autostep = 1
            self._step()

    def cancel_autostep(self, *e):
        #self._autostep_button['text'] = 'Autostep'
        self._autostep = 0

    # Make sure to stop auto-stepping if we get any user input.
    def step(self, *e): self._autostep = 0; self._step()
    def match(self, *e): self._autostep = 0; self._match()
    def expand(self, *e): self._autostep = 0; self._expand()
    def backtrack(self, *e): self._autostep = 0; self._backtrack()

    def _step(self):
        if self._animating_lock: return

        # Try expanding, matching, and backtracking (in that order)
        if self._expand(): pass
        elif self._parser.untried_match() and self._match(): pass
        elif self._backtrack(): pass
        else:
            self._lastoper1['text'] = 'Finished'
            self._lastoper2['text'] = ''
            self._autostep = 0

        # Check if we just completed a parse.
        if self._parser.currently_complete():
            self._autostep = 0
            self._lastoper2['text'] += '    [COMPLETE PARSE]'

    def _expand(self, *e):
        if self._animating_lock: return
        old_frontier = self._parser.frontier()
        rv = self._parser.expand()
        if rv is not None:
            self._lastoper1['text'] = 'Expand:'
            self._lastoper2['text'] = rv
            self._prodlist.selection_clear(0, 'end')
            index = self._productions.index(rv)
            self._prodlist.selection_set(index)
            self._animate_expand(old_frontier[0])
            return 1
        else:
            self._lastoper1['text'] = 'Expand:'
            self._lastoper2['text'] = '(all expansions tried)'
            return 0

    def _match(self, *e):
        if self._animating_lock: return
        old_frontier = self._parser.frontier()
        rv = self._parser.match()
        if rv is not None:
            self._lastoper1['text'] = 'Match:'
            self._lastoper2['text'] = rv
            self._animate_match(old_frontier[0])
            return 1
        else:
            self._lastoper1['text'] = 'Match:'
            self._lastoper2['text'] = '(failed)'
            return 0

    def _backtrack(self, *e):
        if self._animating_lock: return
        if self._parser.backtrack():
            elt = self._parser.tree()
            for i in self._parser.frontier()[0]:
                elt = elt[i]
            self._lastoper1['text'] = 'Backtrack'
            self._lastoper2['text'] = ''
            if isinstance(elt, Tree):
                self._animate_backtrack(self._parser.frontier()[0])
            else:
                self._animate_match_backtrack(self._parser.frontier()[0])
            return 1
        else:
            self._autostep = 0
            self._lastoper1['text'] = 'Finished'
            self._lastoper2['text'] = ''
            return 0

    def about(self, *e):
        ABOUT = ("NLTK Recursive Descent Parser Application\n"+
                 "Written by Edward Loper")
        TITLE = 'About: Recursive Descent Parser Application'
        try:
            from tkMessageBox import Message
            Message(message=ABOUT, title=TITLE).show()
        except:
            ShowText(self._top, TITLE, ABOUT)

    def help(self, *e):
        self._autostep = 0
        # The default font's not very legible; try using 'fixed' instead.
        try:
            ShowText(self._top, 'Help: Recursive Descent Parser Application',
                     (__doc__ or '').strip(), width=75, font='fixed')
        except:
            ShowText(self._top, 'Help: Recursive Descent Parser Application',
                     (__doc__ or '').strip(), width=75)

    def postscript(self, *e):
        self._autostep = 0
        self._cframe.print_to_file()

    def mainloop(self, *args, **kwargs):
        """
        Enter the Tkinter mainloop.  This function must be called if
        this demo is created from a non-interactive program (e.g.
        from a secript); otherwise, the demo will close as soon as
        the script completes.
        """
        if in_idle(): return
        self._top.mainloop(*args, **kwargs)

    def resize(self, size=None):
        if size is not None: self._size.set(size)
        size = self._size.get()
        self._font.configure(size=-(abs(size)))
        self._boldfont.configure(size=-(abs(size)))
        self._sysfont.configure(size=-(abs(size)))
        self._bigfont.configure(size=-(abs(size+2)))
        self._redraw()

    #########################################
    ##  Expand Production Selection
    #########################################

    def _toggle_grammar(self, *e):
        if self._show_grammar.get():
            self._prodframe.pack(fill='both', side='left', padx=2,
                                 after=self._feedbackframe)
            self._lastoper1['text'] = 'Show Grammar'
        else:
            self._prodframe.pack_forget()
            self._lastoper1['text'] = 'Hide Grammar'
        self._lastoper2['text'] = ''

#     def toggle_grammar(self, *e):
#         self._show_grammar = not self._show_grammar
#         if self._show_grammar:
#             self._prodframe.pack(fill='both', expand='y', side='left',
#                                  after=self._feedbackframe)
#             self._lastoper1['text'] = 'Show Grammar'
#         else:
#             self._prodframe.pack_forget()
#             self._lastoper1['text'] = 'Hide Grammar'
#         self._lastoper2['text'] = ''

    def _prodlist_select(self, event):
        selection = self._prodlist.curselection()
        if len(selection) != 1: return
        index = int(selection[0])
        old_frontier = self._parser.frontier()
        production = self._parser.expand(self._productions[index])

        if production:
            self._lastoper1['text'] = 'Expand:'
            self._lastoper2['text'] = production
            self._prodlist.selection_clear(0, 'end')
            self._prodlist.selection_set(index)
            self._animate_expand(old_frontier[0])
        else:
            # Reset the production selections.
            self._prodlist.selection_clear(0, 'end')
            for prod in self._parser.expandable_productions():
                index = self._productions.index(prod)
                self._prodlist.selection_set(index)

    #########################################
    ##  Animation
    #########################################

    def _animate_expand(self, treeloc):
        oldwidget = self._get(self._tree, treeloc)
        oldtree = oldwidget.parent()
        top = not isinstance(oldtree.parent(), TreeSegmentWidget)

        tree = self._parser.tree()
        for i in treeloc:
            tree = tree[i]

        widget = tree_to_treesegment(self._canvas, tree,
                                     node_font=self._boldfont,
                                     leaf_color='white',
                                     tree_width=2, tree_color='white',
                                     node_color='white',
                                     leaf_font=self._font)
        widget.node()['color'] = '#20a050'

        (oldx, oldy) = oldtree.node().bbox()[:2]
        (newx, newy) = widget.node().bbox()[:2]
        widget.move(oldx-newx, oldy-newy)

        if top:
            self._cframe.add_widget(widget, 0, 5)
            widget.move(30-widget.node().bbox()[0], 0)
            self._tree = widget
        else:
            oldtree.parent().replace_child(oldtree, widget)

        # Move the children over so they don't overlap.
        # Line the children up in a strange way.
        if widget.subtrees():
            dx = (oldx + widget.node().width()/2 -
                  widget.subtrees()[0].bbox()[0]/2 -
                  widget.subtrees()[0].bbox()[2]/2)
            for subtree in widget.subtrees(): subtree.move(dx, 0)

        self._makeroom(widget)

        if top:
            self._cframe.destroy_widget(oldtree)
        else:
            oldtree.destroy()

        colors = ['gray%d' % (10*int(10*x/self._animation_frames.get()))
                  for x in range(self._animation_frames.get(),0,-1)]

        # Move the text string down, if necessary.
        dy = widget.bbox()[3] + 30 - self._canvas.coords(self._textline)[1]
        if dy > 0:
            for twidget in self._textwidgets: twidget.move(0, dy)
            self._canvas.move(self._textline, 0, dy)

        self._animate_expand_frame(widget, colors)

    def _makeroom(self, treeseg):
        """
        Make sure that no sibling tree bbox's overlap.
        """
        parent = treeseg.parent()
        if not isinstance(parent, TreeSegmentWidget): return

        index = parent.subtrees().index(treeseg)

        # Handle siblings to the right
        rsiblings = parent.subtrees()[index+1:]
        if rsiblings:
            dx = treeseg.bbox()[2] - rsiblings[0].bbox()[0] + 10
            for sibling in rsiblings: sibling.move(dx, 0)

        # Handle siblings to the left
        if index > 0:
            lsibling = parent.subtrees()[index-1]
            dx = max(0, lsibling.bbox()[2] - treeseg.bbox()[0] + 10)
            treeseg.move(dx, 0)

        # Keep working up the tree.
        self._makeroom(parent)

    def _animate_expand_frame(self, widget, colors):
        if len(colors) > 0:
            self._animating_lock = 1
            widget['color'] = colors[0]
            for subtree in widget.subtrees():
                if isinstance(subtree, TreeSegmentWidget):
                    subtree.node()['color'] = colors[0]
                else:
                    subtree['color'] = colors[0]
            self._top.after(50, self._animate_expand_frame,
                            widget, colors[1:])
        else:
            widget['color'] = 'black'
            for subtree in widget.subtrees():
                if isinstance(subtree, TreeSegmentWidget):
                    subtree.node()['color'] = 'black'
                else:
                    subtree['color'] = 'black'
            self._redraw_quick()
            widget.node()['color'] = 'black'
            self._animating_lock = 0
            if self._autostep: self._step()

    def _animate_backtrack(self, treeloc):
        # Flash red first, if we're animating.
        if self._animation_frames.get() == 0: colors = []
        else: colors = ['#a00000', '#000000', '#a00000']
        colors += ['gray%d' % (10*int(10*x/(self._animation_frames.get())))
                   for x in range(1, self._animation_frames.get()+1)]

        widgets = [self._get(self._tree, treeloc).parent()]
        for subtree in widgets[0].subtrees():
            if isinstance(subtree, TreeSegmentWidget):
                widgets.append(subtree.node())
            else:
                widgets.append(subtree)

        self._animate_backtrack_frame(widgets, colors)

    def _animate_backtrack_frame(self, widgets, colors):
        if len(colors) > 0:
            self._animating_lock = 1
            for widget in widgets: widget['color'] = colors[0]
            self._top.after(50, self._animate_backtrack_frame,
                            widgets, colors[1:])
        else:
            for widget in widgets[0].subtrees():
                widgets[0].remove_child(widget)
                widget.destroy()
            self._redraw_quick()
            self._animating_lock = 0
            if self._autostep: self._step()

    def _animate_match_backtrack(self, treeloc):
        widget = self._get(self._tree, treeloc)
        node = widget.parent().node()
        dy = (1.0 * (node.bbox()[3] - widget.bbox()[1] + 14) /
              max(1, self._animation_frames.get()))
        self._animate_match_backtrack_frame(self._animation_frames.get(),
                                            widget, dy)

    def _animate_match(self, treeloc):
        widget = self._get(self._tree, treeloc)

        dy = ((self._textwidgets[0].bbox()[1] - widget.bbox()[3] - 10.0) /
              max(1, self._animation_frames.get()))
        self._animate_match_frame(self._animation_frames.get(), widget, dy)

    def _animate_match_frame(self, frame, widget, dy):
        if frame > 0:
            self._animating_lock = 1
            widget.move(0, dy)
            self._top.after(10, self._animate_match_frame,
                            frame-1, widget, dy)
        else:
            widget['color'] = '#006040'
            self._redraw_quick()
            self._animating_lock = 0
            if self._autostep: self._step()

    def _animate_match_backtrack_frame(self, frame, widget, dy):
        if frame > 0:
            self._animating_lock = 1
            widget.move(0, dy)
            self._top.after(10, self._animate_match_backtrack_frame,
                            frame-1, widget, dy)
        else:
            widget.parent().remove_child(widget)
            widget.destroy()
            self._animating_lock = 0
            if self._autostep: self._step()

    def edit_grammar(self, *e):
        CFGEditor(self._top, self._parser.grammar(), self.set_grammar)

    def set_grammar(self, grammar):
        self._parser.set_grammar(grammar)
        self._productions = list(grammar.productions())
        self._prodlist.delete(0, 'end')
        for production in self._productions:
            self._prodlist.insert('end', (' %s' % production))

    def edit_sentence(self, *e):
        sentence = " ".join(self._sent)
        title = 'Edit Text'
        instr = 'Enter a new sentence to parse.'
        EntryDialog(self._top, sentence, instr, self.set_sentence, title)

    def set_sentence(self, sentence):
        self._sent = sentence.split() #[XX] use tagged?
        self.reset()
Example #47
0
class RecursiveDescentApp(object):
    """
    A graphical tool for exploring the recursive descent parser.  The tool
    displays the parser's tree and the remaining text, and allows the
    user to control the parser's operation.  In particular, the user
    can expand subtrees on the frontier, match tokens on the frontier
    against the text, and backtrack.  A "step" button simply steps
    through the parsing process, performing the operations that
    ``RecursiveDescentParser`` would use.
    """
    def __init__(self, grammar, sent, trace=0):
        self._sent = sent
        self._parser = SteppingRecursiveDescentParser(grammar, trace)

        # Set up the main window.
        self._top = Tk()
        self._top.title('Recursive Descent Parser Application')

        # Set up key bindings.
        self._init_bindings()

        # Initialize the fonts.
        self._init_fonts(self._top)

        # Animations.  animating_lock is a lock to prevent the demo
        # from performing new operations while it's animating.
        self._animation_frames = IntVar(self._top)
        self._animation_frames.set(5)
        self._animating_lock = 0
        self._autostep = 0

        # The user can hide the grammar.
        self._show_grammar = IntVar(self._top)
        self._show_grammar.set(1)

        # Create the basic frames.
        self._init_menubar(self._top)
        self._init_buttons(self._top)
        self._init_feedback(self._top)
        self._init_grammar(self._top)
        self._init_canvas(self._top)

        # Initialize the parser.
        self._parser.initialize(self._sent)

        # Resize callback
        self._canvas.bind('<Configure>', self._configure)

    #########################################
    ##  Initialization Helpers
    #########################################

    def _init_fonts(self, root):
        # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html>
        self._sysfont = tkinter.font.Font(font=Button()["font"])
        root.option_add("*Font", self._sysfont)

        # TWhat's our font size (default=same as sysfont)
        self._size = IntVar(root)
        self._size.set(self._sysfont.cget('size'))

        self._boldfont = tkinter.font.Font(family='helvetica',
                                           weight='bold',
                                           size=self._size.get())
        self._font = tkinter.font.Font(family='helvetica',
                                       size=self._size.get())
        if self._size.get() < 0: big = self._size.get() - 2
        else: big = self._size.get() + 2
        self._bigfont = tkinter.font.Font(family='helvetica',
                                          weight='bold',
                                          size=big)

    def _init_grammar(self, parent):
        # Grammar view.
        self._prodframe = listframe = Frame(parent)
        self._prodframe.pack(fill='both', side='left', padx=2)
        self._prodlist_label = Label(self._prodframe,
                                     font=self._boldfont,
                                     text='Available Expansions')
        self._prodlist_label.pack()
        self._prodlist = Listbox(self._prodframe,
                                 selectmode='single',
                                 relief='groove',
                                 background='white',
                                 foreground='#909090',
                                 font=self._font,
                                 selectforeground='#004040',
                                 selectbackground='#c0f0c0')

        self._prodlist.pack(side='right', fill='both', expand=1)

        self._productions = list(self._parser.grammar().productions())
        for production in self._productions:
            self._prodlist.insert('end', ('  %s' % production))
        self._prodlist.config(height=min(len(self._productions), 25))

        # Add a scrollbar if there are more than 25 productions.
        if len(self._productions) > 25:
            listscroll = Scrollbar(self._prodframe, orient='vertical')
            self._prodlist.config(yscrollcommand=listscroll.set)
            listscroll.config(command=self._prodlist.yview)
            listscroll.pack(side='left', fill='y')

        # If they select a production, apply it.
        self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select)

    def _init_bindings(self):
        # Key bindings are a good thing.
        self._top.bind('<Control-q>', self.destroy)
        self._top.bind('<Control-x>', self.destroy)
        self._top.bind('<Escape>', self.destroy)
        self._top.bind('e', self.expand)
        #self._top.bind('<Alt-e>', self.expand)
        #self._top.bind('<Control-e>', self.expand)
        self._top.bind('m', self.match)
        self._top.bind('<Alt-m>', self.match)
        self._top.bind('<Control-m>', self.match)
        self._top.bind('b', self.backtrack)
        self._top.bind('<Alt-b>', self.backtrack)
        self._top.bind('<Control-b>', self.backtrack)
        self._top.bind('<Control-z>', self.backtrack)
        self._top.bind('<BackSpace>', self.backtrack)
        self._top.bind('a', self.autostep)
        #self._top.bind('<Control-a>', self.autostep)
        self._top.bind('<Control-space>', self.autostep)
        self._top.bind('<Control-c>', self.cancel_autostep)
        self._top.bind('<space>', self.step)
        self._top.bind('<Delete>', self.reset)
        self._top.bind('<Control-p>', self.postscript)
        #self._top.bind('<h>', self.help)
        #self._top.bind('<Alt-h>', self.help)
        self._top.bind('<Control-h>', self.help)
        self._top.bind('<F1>', self.help)
        #self._top.bind('<g>', self.toggle_grammar)
        #self._top.bind('<Alt-g>', self.toggle_grammar)
        #self._top.bind('<Control-g>', self.toggle_grammar)
        self._top.bind('<Control-g>', self.edit_grammar)
        self._top.bind('<Control-t>', self.edit_sentence)

    def _init_buttons(self, parent):
        # Set up the frames.
        self._buttonframe = buttonframe = Frame(parent)
        buttonframe.pack(fill='none', side='bottom', padx=3, pady=2)
        Button(
            buttonframe,
            text='Step',
            background='#90c0d0',
            foreground='black',
            command=self.step,
        ).pack(side='left')
        Button(
            buttonframe,
            text='Autostep',
            background='#90c0d0',
            foreground='black',
            command=self.autostep,
        ).pack(side='left')
        Button(buttonframe,
               text='Expand',
               underline=0,
               background='#90f090',
               foreground='black',
               command=self.expand).pack(side='left')
        Button(buttonframe,
               text='Match',
               underline=0,
               background='#90f090',
               foreground='black',
               command=self.match).pack(side='left')
        Button(buttonframe,
               text='Backtrack',
               underline=0,
               background='#f0a0a0',
               foreground='black',
               command=self.backtrack).pack(side='left')
        # Replace autostep...
#         self._autostep_button = Button(buttonframe, text='Autostep',
#                                        underline=0, command=self.autostep)
#         self._autostep_button.pack(side='left')

    def _configure(self, event):
        self._autostep = 0
        (x1, y1, x2, y2) = self._cframe.scrollregion()
        y2 = event.height - 6
        self._canvas['scrollregion'] = '%d %d %d %d' % (x1, y1, x2, y2)
        self._redraw()

    def _init_feedback(self, parent):
        self._feedbackframe = feedbackframe = Frame(parent)
        feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3)
        self._lastoper_label = Label(feedbackframe,
                                     text='Last Operation:',
                                     font=self._font)
        self._lastoper_label.pack(side='left')
        lastoperframe = Frame(feedbackframe, relief='sunken', border=1)
        lastoperframe.pack(fill='x', side='right', expand=1, padx=5)
        self._lastoper1 = Label(lastoperframe,
                                foreground='#007070',
                                background='#f0f0f0',
                                font=self._font)
        self._lastoper2 = Label(lastoperframe,
                                anchor='w',
                                width=30,
                                foreground='#004040',
                                background='#f0f0f0',
                                font=self._font)
        self._lastoper1.pack(side='left')
        self._lastoper2.pack(side='left', fill='x', expand=1)

    def _init_canvas(self, parent):
        self._cframe = CanvasFrame(
            parent,
            background='white',
            #width=525, height=250,
            closeenough=10,
            border=2,
            relief='sunken')
        self._cframe.pack(expand=1, fill='both', side='top', pady=2)
        canvas = self._canvas = self._cframe.canvas()

        # Initially, there's no tree or text
        self._tree = None
        self._textwidgets = []
        self._textline = None

    def _init_menubar(self, parent):
        menubar = Menu(parent)

        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label='Reset Parser',
                             underline=0,
                             command=self.reset,
                             accelerator='Del')
        filemenu.add_command(label='Print to Postscript',
                             underline=0,
                             command=self.postscript,
                             accelerator='Ctrl-p')
        filemenu.add_command(label='Exit',
                             underline=1,
                             command=self.destroy,
                             accelerator='Ctrl-x')
        menubar.add_cascade(label='File', underline=0, menu=filemenu)

        editmenu = Menu(menubar, tearoff=0)
        editmenu.add_command(label='Edit Grammar',
                             underline=5,
                             command=self.edit_grammar,
                             accelerator='Ctrl-g')
        editmenu.add_command(label='Edit Text',
                             underline=5,
                             command=self.edit_sentence,
                             accelerator='Ctrl-t')
        menubar.add_cascade(label='Edit', underline=0, menu=editmenu)

        rulemenu = Menu(menubar, tearoff=0)
        rulemenu.add_command(label='Step',
                             underline=1,
                             command=self.step,
                             accelerator='Space')
        rulemenu.add_separator()
        rulemenu.add_command(label='Match',
                             underline=0,
                             command=self.match,
                             accelerator='Ctrl-m')
        rulemenu.add_command(label='Expand',
                             underline=0,
                             command=self.expand,
                             accelerator='Ctrl-e')
        rulemenu.add_separator()
        rulemenu.add_command(label='Backtrack',
                             underline=0,
                             command=self.backtrack,
                             accelerator='Ctrl-b')
        menubar.add_cascade(label='Apply', underline=0, menu=rulemenu)

        viewmenu = Menu(menubar, tearoff=0)
        viewmenu.add_checkbutton(label="Show Grammar",
                                 underline=0,
                                 variable=self._show_grammar,
                                 command=self._toggle_grammar)
        viewmenu.add_separator()
        viewmenu.add_radiobutton(label='Tiny',
                                 variable=self._size,
                                 underline=0,
                                 value=10,
                                 command=self.resize)
        viewmenu.add_radiobutton(label='Small',
                                 variable=self._size,
                                 underline=0,
                                 value=12,
                                 command=self.resize)
        viewmenu.add_radiobutton(label='Medium',
                                 variable=self._size,
                                 underline=0,
                                 value=14,
                                 command=self.resize)
        viewmenu.add_radiobutton(label='Large',
                                 variable=self._size,
                                 underline=0,
                                 value=18,
                                 command=self.resize)
        viewmenu.add_radiobutton(label='Huge',
                                 variable=self._size,
                                 underline=0,
                                 value=24,
                                 command=self.resize)
        menubar.add_cascade(label='View', underline=0, menu=viewmenu)

        animatemenu = Menu(menubar, tearoff=0)
        animatemenu.add_radiobutton(label="No Animation",
                                    underline=0,
                                    variable=self._animation_frames,
                                    value=0)
        animatemenu.add_radiobutton(label="Slow Animation",
                                    underline=0,
                                    variable=self._animation_frames,
                                    value=10,
                                    accelerator='-')
        animatemenu.add_radiobutton(label="Normal Animation",
                                    underline=0,
                                    variable=self._animation_frames,
                                    value=5,
                                    accelerator='=')
        animatemenu.add_radiobutton(label="Fast Animation",
                                    underline=0,
                                    variable=self._animation_frames,
                                    value=2,
                                    accelerator='+')
        menubar.add_cascade(label="Animate", underline=1, menu=animatemenu)

        helpmenu = Menu(menubar, tearoff=0)
        helpmenu.add_command(label='About', underline=0, command=self.about)
        helpmenu.add_command(label='Instructions',
                             underline=0,
                             command=self.help,
                             accelerator='F1')
        menubar.add_cascade(label='Help', underline=0, menu=helpmenu)

        parent.config(menu=menubar)

    #########################################
    ##  Helper
    #########################################

    def _get(self, widget, treeloc):
        for i in treeloc:
            widget = widget.subtrees()[i]
        if isinstance(widget, TreeSegmentWidget):
            widget = widget.label()
        return widget

    #########################################
    ##  Main draw procedure
    #########################################

    def _redraw(self):
        canvas = self._canvas

        # Delete the old tree, widgets, etc.
        if self._tree is not None:
            self._cframe.destroy_widget(self._tree)
        for twidget in self._textwidgets:
            self._cframe.destroy_widget(twidget)
        if self._textline is not None:
            self._canvas.delete(self._textline)

        # Draw the tree.
        helv = ('helvetica', -self._size.get())
        bold = ('helvetica', -self._size.get(), 'bold')
        attribs = {
            'tree_color': '#000000',
            'tree_width': 2,
            'node_font': bold,
            'leaf_font': helv,
        }
        tree = self._parser.tree()
        self._tree = tree_to_treesegment(canvas, tree, **attribs)
        self._cframe.add_widget(self._tree, 30, 5)

        # Draw the text.
        helv = ('helvetica', -self._size.get())
        bottom = y = self._cframe.scrollregion()[3]
        self._textwidgets = [
            TextWidget(canvas, word, font=self._font) for word in self._sent
        ]
        for twidget in self._textwidgets:
            self._cframe.add_widget(twidget, 0, 0)
            twidget.move(0, bottom - twidget.bbox()[3] - 5)
            y = min(y, twidget.bbox()[1])

        # Draw a line over the text, to separate it from the tree.
        self._textline = canvas.create_line(-5000,
                                            y - 5,
                                            5000,
                                            y - 5,
                                            dash='.')

        # Highlight appropriate nodes.
        self._highlight_nodes()
        self._highlight_prodlist()

        # Make sure the text lines up.
        self._position_text()

    def _redraw_quick(self):
        # This should be more-or-less sufficient after an animation.
        self._highlight_nodes()
        self._highlight_prodlist()
        self._position_text()

    def _highlight_nodes(self):
        # Highlight the list of nodes to be checked.
        bold = ('helvetica', -self._size.get(), 'bold')
        for treeloc in self._parser.frontier()[:1]:
            self._get(self._tree, treeloc)['color'] = '#20a050'
            self._get(self._tree, treeloc)['font'] = bold
        for treeloc in self._parser.frontier()[1:]:
            self._get(self._tree, treeloc)['color'] = '#008080'

    def _highlight_prodlist(self):
        # Highlight the productions that can be expanded.
        # Boy, too bad tkinter doesn't implement Listbox.itemconfig;
        # that would be pretty useful here.
        self._prodlist.delete(0, 'end')
        expandable = self._parser.expandable_productions()
        untried = self._parser.untried_expandable_productions()
        productions = self._productions
        for index in range(len(productions)):
            if productions[index] in expandable:
                if productions[index] in untried:
                    self._prodlist.insert(index, ' %s' % productions[index])
                else:
                    self._prodlist.insert(index,
                                          ' %s (TRIED)' % productions[index])
                self._prodlist.selection_set(index)
            else:
                self._prodlist.insert(index, ' %s' % productions[index])

    def _position_text(self):
        # Line up the text widgets that are matched against the tree
        numwords = len(self._sent)
        num_matched = numwords - len(self._parser.remaining_text())
        leaves = self._tree_leaves()[:num_matched]
        xmax = self._tree.bbox()[0]
        for i in range(0, len(leaves)):
            widget = self._textwidgets[i]
            leaf = leaves[i]
            widget['color'] = '#006040'
            leaf['color'] = '#006040'
            widget.move(leaf.bbox()[0] - widget.bbox()[0], 0)
            xmax = widget.bbox()[2] + 10

        # Line up the text widgets that are not matched against the tree.
        for i in range(len(leaves), numwords):
            widget = self._textwidgets[i]
            widget['color'] = '#a0a0a0'
            widget.move(xmax - widget.bbox()[0], 0)
            xmax = widget.bbox()[2] + 10

        # If we have a complete parse, make everything green :)
        if self._parser.currently_complete():
            for twidget in self._textwidgets:
                twidget['color'] = '#00a000'

        # Move the matched leaves down to the text.
        for i in range(0, len(leaves)):
            widget = self._textwidgets[i]
            leaf = leaves[i]
            dy = widget.bbox()[1] - leaf.bbox()[3] - 10.0
            dy = max(dy, leaf.parent().label().bbox()[3] - leaf.bbox()[3] + 10)
            leaf.move(0, dy)

    def _tree_leaves(self, tree=None):
        if tree is None: tree = self._tree
        if isinstance(tree, TreeSegmentWidget):
            leaves = []
            for child in tree.subtrees():
                leaves += self._tree_leaves(child)
            return leaves
        else:
            return [tree]

    #########################################
    ##  Button Callbacks
    #########################################

    def destroy(self, *e):
        self._autostep = 0
        if self._top is None: return
        self._top.destroy()
        self._top = None

    def reset(self, *e):
        self._autostep = 0
        self._parser.initialize(self._sent)
        self._lastoper1['text'] = 'Reset Application'
        self._lastoper2['text'] = ''
        self._redraw()

    def autostep(self, *e):
        if self._animation_frames.get() == 0:
            self._animation_frames.set(2)
        if self._autostep:
            self._autostep = 0
        else:
            self._autostep = 1
            self._step()

    def cancel_autostep(self, *e):
        #self._autostep_button['text'] = 'Autostep'
        self._autostep = 0

    # Make sure to stop auto-stepping if we get any user input.
    def step(self, *e):
        self._autostep = 0
        self._step()

    def match(self, *e):
        self._autostep = 0
        self._match()

    def expand(self, *e):
        self._autostep = 0
        self._expand()

    def backtrack(self, *e):
        self._autostep = 0
        self._backtrack()

    def _step(self):
        if self._animating_lock: return

        # Try expanding, matching, and backtracking (in that order)
        if self._expand(): pass
        elif self._parser.untried_match() and self._match(): pass
        elif self._backtrack(): pass
        else:
            self._lastoper1['text'] = 'Finished'
            self._lastoper2['text'] = ''
            self._autostep = 0

        # Check if we just completed a parse.
        if self._parser.currently_complete():
            self._autostep = 0
            self._lastoper2['text'] += '    [COMPLETE PARSE]'

    def _expand(self, *e):
        if self._animating_lock: return
        old_frontier = self._parser.frontier()
        rv = self._parser.expand()
        if rv is not None:
            self._lastoper1['text'] = 'Expand:'
            self._lastoper2['text'] = rv
            self._prodlist.selection_clear(0, 'end')
            index = self._productions.index(rv)
            self._prodlist.selection_set(index)
            self._animate_expand(old_frontier[0])
            return True
        else:
            self._lastoper1['text'] = 'Expand:'
            self._lastoper2['text'] = '(all expansions tried)'
            return False

    def _match(self, *e):
        if self._animating_lock: return
        old_frontier = self._parser.frontier()
        rv = self._parser.match()
        if rv is not None:
            self._lastoper1['text'] = 'Match:'
            self._lastoper2['text'] = rv
            self._animate_match(old_frontier[0])
            return True
        else:
            self._lastoper1['text'] = 'Match:'
            self._lastoper2['text'] = '(failed)'
            return False

    def _backtrack(self, *e):
        if self._animating_lock: return
        if self._parser.backtrack():
            elt = self._parser.tree()
            for i in self._parser.frontier()[0]:
                elt = elt[i]
            self._lastoper1['text'] = 'Backtrack'
            self._lastoper2['text'] = ''
            if isinstance(elt, Tree):
                self._animate_backtrack(self._parser.frontier()[0])
            else:
                self._animate_match_backtrack(self._parser.frontier()[0])
            return True
        else:
            self._autostep = 0
            self._lastoper1['text'] = 'Finished'
            self._lastoper2['text'] = ''
            return False

    def about(self, *e):
        ABOUT = ("NLTK Recursive Descent Parser Application\n" +
                 "Written by Edward Loper")
        TITLE = 'About: Recursive Descent Parser Application'
        try:
            from tkinter.messagebox import Message
            Message(message=ABOUT, title=TITLE).show()
        except:
            ShowText(self._top, TITLE, ABOUT)

    def help(self, *e):
        self._autostep = 0
        # The default font's not very legible; try using 'fixed' instead.
        try:
            ShowText(self._top,
                     'Help: Recursive Descent Parser Application',
                     (__doc__ or '').strip(),
                     width=75,
                     font='fixed')
        except:
            ShowText(self._top,
                     'Help: Recursive Descent Parser Application',
                     (__doc__ or '').strip(),
                     width=75)

    def postscript(self, *e):
        self._autostep = 0
        self._cframe.print_to_file()

    def mainloop(self, *args, **kwargs):
        """
        Enter the Tkinter mainloop.  This function must be called if
        this demo is created from a non-interactive program (e.g.
        from a secript); otherwise, the demo will close as soon as
        the script completes.
        """
        if in_idle(): return
        self._top.mainloop(*args, **kwargs)

    def resize(self, size=None):
        if size is not None: self._size.set(size)
        size = self._size.get()
        self._font.configure(size=-(abs(size)))
        self._boldfont.configure(size=-(abs(size)))
        self._sysfont.configure(size=-(abs(size)))
        self._bigfont.configure(size=-(abs(size + 2)))
        self._redraw()

    #########################################
    ##  Expand Production Selection
    #########################################

    def _toggle_grammar(self, *e):
        if self._show_grammar.get():
            self._prodframe.pack(fill='both',
                                 side='left',
                                 padx=2,
                                 after=self._feedbackframe)
            self._lastoper1['text'] = 'Show Grammar'
        else:
            self._prodframe.pack_forget()
            self._lastoper1['text'] = 'Hide Grammar'
        self._lastoper2['text'] = ''


#     def toggle_grammar(self, *e):
#         self._show_grammar = not self._show_grammar
#         if self._show_grammar:
#             self._prodframe.pack(fill='both', expand='y', side='left',
#                                  after=self._feedbackframe)
#             self._lastoper1['text'] = 'Show Grammar'
#         else:
#             self._prodframe.pack_forget()
#             self._lastoper1['text'] = 'Hide Grammar'
#         self._lastoper2['text'] = ''

    def _prodlist_select(self, event):
        selection = self._prodlist.curselection()
        if len(selection) != 1: return
        index = int(selection[0])
        old_frontier = self._parser.frontier()
        production = self._parser.expand(self._productions[index])

        if production:
            self._lastoper1['text'] = 'Expand:'
            self._lastoper2['text'] = production
            self._prodlist.selection_clear(0, 'end')
            self._prodlist.selection_set(index)
            self._animate_expand(old_frontier[0])
        else:
            # Reset the production selections.
            self._prodlist.selection_clear(0, 'end')
            for prod in self._parser.expandable_productions():
                index = self._productions.index(prod)
                self._prodlist.selection_set(index)

    #########################################
    ##  Animation
    #########################################

    def _animate_expand(self, treeloc):
        oldwidget = self._get(self._tree, treeloc)
        oldtree = oldwidget.parent()
        top = not isinstance(oldtree.parent(), TreeSegmentWidget)

        tree = self._parser.tree()
        for i in treeloc:
            tree = tree[i]

        widget = tree_to_treesegment(self._canvas,
                                     tree,
                                     node_font=self._boldfont,
                                     leaf_color='white',
                                     tree_width=2,
                                     tree_color='white',
                                     node_color='white',
                                     leaf_font=self._font)
        widget.label()['color'] = '#20a050'

        (oldx, oldy) = oldtree.label().bbox()[:2]
        (newx, newy) = widget.label().bbox()[:2]
        widget.move(oldx - newx, oldy - newy)

        if top:
            self._cframe.add_widget(widget, 0, 5)
            widget.move(30 - widget.label().bbox()[0], 0)
            self._tree = widget
        else:
            oldtree.parent().replace_child(oldtree, widget)

        # Move the children over so they don't overlap.
        # Line the children up in a strange way.
        if widget.subtrees():
            dx = (oldx + widget.label().width() / 2 -
                  widget.subtrees()[0].bbox()[0] / 2 -
                  widget.subtrees()[0].bbox()[2] / 2)
            for subtree in widget.subtrees():
                subtree.move(dx, 0)

        self._makeroom(widget)

        if top:
            self._cframe.destroy_widget(oldtree)
        else:
            oldtree.destroy()

        colors = [
            'gray%d' % (10 * int(10 * x / self._animation_frames.get()))
            for x in range(self._animation_frames.get(), 0, -1)
        ]

        # Move the text string down, if necessary.
        dy = widget.bbox()[3] + 30 - self._canvas.coords(self._textline)[1]
        if dy > 0:
            for twidget in self._textwidgets:
                twidget.move(0, dy)
            self._canvas.move(self._textline, 0, dy)

        self._animate_expand_frame(widget, colors)

    def _makeroom(self, treeseg):
        """
        Make sure that no sibling tree bbox's overlap.
        """
        parent = treeseg.parent()
        if not isinstance(parent, TreeSegmentWidget): return

        index = parent.subtrees().index(treeseg)

        # Handle siblings to the right
        rsiblings = parent.subtrees()[index + 1:]
        if rsiblings:
            dx = treeseg.bbox()[2] - rsiblings[0].bbox()[0] + 10
            for sibling in rsiblings:
                sibling.move(dx, 0)

        # Handle siblings to the left
        if index > 0:
            lsibling = parent.subtrees()[index - 1]
            dx = max(0, lsibling.bbox()[2] - treeseg.bbox()[0] + 10)
            treeseg.move(dx, 0)

        # Keep working up the tree.
        self._makeroom(parent)

    def _animate_expand_frame(self, widget, colors):
        if len(colors) > 0:
            self._animating_lock = 1
            widget['color'] = colors[0]
            for subtree in widget.subtrees():
                if isinstance(subtree, TreeSegmentWidget):
                    subtree.label()['color'] = colors[0]
                else:
                    subtree['color'] = colors[0]
            self._top.after(50, self._animate_expand_frame, widget, colors[1:])
        else:
            widget['color'] = 'black'
            for subtree in widget.subtrees():
                if isinstance(subtree, TreeSegmentWidget):
                    subtree.label()['color'] = 'black'
                else:
                    subtree['color'] = 'black'
            self._redraw_quick()
            widget.label()['color'] = 'black'
            self._animating_lock = 0
            if self._autostep: self._step()

    def _animate_backtrack(self, treeloc):
        # Flash red first, if we're animating.
        if self._animation_frames.get() == 0: colors = []
        else: colors = ['#a00000', '#000000', '#a00000']
        colors += [
            'gray%d' % (10 * int(10 * x / (self._animation_frames.get())))
            for x in range(1,
                           self._animation_frames.get() + 1)
        ]

        widgets = [self._get(self._tree, treeloc).parent()]
        for subtree in widgets[0].subtrees():
            if isinstance(subtree, TreeSegmentWidget):
                widgets.append(subtree.label())
            else:
                widgets.append(subtree)

        self._animate_backtrack_frame(widgets, colors)

    def _animate_backtrack_frame(self, widgets, colors):
        if len(colors) > 0:
            self._animating_lock = 1
            for widget in widgets:
                widget['color'] = colors[0]
            self._top.after(50, self._animate_backtrack_frame, widgets,
                            colors[1:])
        else:
            for widget in widgets[0].subtrees():
                widgets[0].remove_child(widget)
                widget.destroy()
            self._redraw_quick()
            self._animating_lock = 0
            if self._autostep: self._step()

    def _animate_match_backtrack(self, treeloc):
        widget = self._get(self._tree, treeloc)
        node = widget.parent().label()
        dy = (1.0 * (node.bbox()[3] - widget.bbox()[1] + 14) /
              max(1, self._animation_frames.get()))
        self._animate_match_backtrack_frame(self._animation_frames.get(),
                                            widget, dy)

    def _animate_match(self, treeloc):
        widget = self._get(self._tree, treeloc)

        dy = ((self._textwidgets[0].bbox()[1] - widget.bbox()[3] - 10.0) /
              max(1, self._animation_frames.get()))
        self._animate_match_frame(self._animation_frames.get(), widget, dy)

    def _animate_match_frame(self, frame, widget, dy):
        if frame > 0:
            self._animating_lock = 1
            widget.move(0, dy)
            self._top.after(10, self._animate_match_frame, frame - 1, widget,
                            dy)
        else:
            widget['color'] = '#006040'
            self._redraw_quick()
            self._animating_lock = 0
            if self._autostep: self._step()

    def _animate_match_backtrack_frame(self, frame, widget, dy):
        if frame > 0:
            self._animating_lock = 1
            widget.move(0, dy)
            self._top.after(10, self._animate_match_backtrack_frame, frame - 1,
                            widget, dy)
        else:
            widget.parent().remove_child(widget)
            widget.destroy()
            self._animating_lock = 0
            if self._autostep: self._step()

    def edit_grammar(self, *e):
        CFGEditor(self._top, self._parser.grammar(), self.set_grammar)

    def set_grammar(self, grammar):
        self._parser.set_grammar(grammar)
        self._productions = list(grammar.productions())
        self._prodlist.delete(0, 'end')
        for production in self._productions:
            self._prodlist.insert('end', (' %s' % production))

    def edit_sentence(self, *e):
        sentence = " ".join(self._sent)
        title = 'Edit Text'
        instr = 'Enter a new sentence to parse.'
        EntryDialog(self._top, sentence, instr, self.set_sentence, title)

    def set_sentence(self, sentence):
        self._sent = sentence.split()  #[XX] use tagged?
        self.reset()
Example #48
0
#-*- coding: utf8 -*-
__author__ = 'dasolma'
from parser import *
from nltk import Tree
from nltk.draw.util import CanvasFrame
from nltk.draw import TreeWidget

sentences = ["¿ Como está la luz del dormitorio ?",
             "Enciende la luz de la cocina",
             "configura el aire acondicionado a 26 grados a las 6 pm hasta las 7:20 am",
             "Apaga el aire acondicionado",
             "Apaga el horno",
             "¿ Como está la puerta de la cocina ?",
             "Enciende el aire acondicionado"]


count = 1
for sent in sentences:
    print sent
    trees = parse(sent)
    if len(trees) == 0: print "No parser"
    else:
        for t in trees:
            cf = CanvasFrame()
            tc = TreeWidget(cf.canvas(),t)
            cf.add_widget(tc,10,10) # (10,10) offsets
            cf.print_to_file('tree%d.ps'%count)
            cf.destroy()
            count +=1