#!/usr/bin/env python # -*- coding: utf-8 -*- # # treant-js # # [treant-js](http://fperucic.github.io/treant-js/) is a javascript library to plot diagram and trees. The goal is to wrap it as a library for python. # [documentation](http://fperucic.github.io/treant-js/) [source](https://github.com/fperucic/treant-js) [tutorial](http://help.plot.ly/tutorials/) [gallery](http://fperucic.github.io/treant-js/#orgchart-examples) # In[1]: from jyquickhelper import add_notebook_menu add_notebook_menu() # ## Javacript in the notebook # # Let's take one of the example and look at the source: [tennis draw](http://fperucic.github.io/treant-js/examples/tennis-draw/). I took the source of the example and I changed relative to absolute paths. There are two parts: # # * HTML: defines styles, references external script, new HTML and section div # * Javascript: defines a tree structure as Json and calls *treant-js* to convert it into SVG. # In[2]: get_ipython().run_cell_magic('html', '', '\n\n\n\n\n\n
\n') # In[3]: get_ipython().run_cell_magic('javascript', '', '\n// source: \n// http://www.atpworldtour.com/Share/Event-Draws.aspx?EventId=410&Year=2013\n\nvar tree_structure = {\n chart: {\n container: "#OrganiseChart6",\n levelSeparation: 20,\n siblingSeparation: 15,\n subTeeSeparation: 15,\n rootOrientation: "EAST",\n\n node: {\n HTMLclass: "tennis-draw",\n drawLineThrough: true\n },\n connectors: {\n type: "straight",\n style: {\n "stroke-width": 2,\n "stroke": "#ccc"\n }\n }\n },\n \n nodeStructure: {\n text: {\n name: {val: "Djokovic, Novak", \n href: "http://www.atpworldtour.com/Tennis/Players/Top-Players/Novak-Djokovic.aspx"}\n },\n HTMLclass: "winner",\n children: [\n {\n text: {\n name: "Djokovic, Novak",\n desc: "4-6, 6-2, 6-2"\n },\n children: [\n {\n text: {\n name: "Djokovic, Novak",\n desc: "4-6, 6-1, 6-4"\n },\n children: [\n {\n text: {\n name: "Djokovic, Novak",\n desc: "4-6, 6-1, 6-4"\n },\n children: [\n {\n text: { \n name: "Djokovic, Novak",\n title: 1\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/srb.jpg",\n HTMLclass: "first-draw",\n },\n {\n text: { \n name: "Bye",\n title: 2\n },\n HTMLclass: "first-draw bye"\n }\n ]\n },\n {\n text: {\n name: "Youzhny, Mikhail",\n desc: "6-4, 6-0"\n },\n children: [\n {\n text: { \n name: "Youzhny, Mikhail",\n title: 3\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/rus.jpg",\n HTMLclass: "first-draw"\n },\n {\n text: { \n name: "Gimeno-Traver, Daniel",\n title: 4\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/esp.jpg",\n HTMLclass: "first-draw"\n }\n ]\n }\n ]\n },\n {\n text: {\n name: "Monaco, Juan",\n desc: "6-0, 3-6, 6-3"\n },\n children: [\n {\n text: {\n name: "Gulbis, Ernests",\n desc: "4-6, 6-2, 6-3"\n },\n children: [\n {\n text: {\n name: "Gulbis, Ernests",\n title: 5\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/lat.jpg",\n HTMLclass: "first-draw"\n },\n {\n text: { \n name: "Isner, John",\n title: 6\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/usa.jpg",\n HTMLclass: "first-draw"\n }\n ]\n },\n {\n text: {\n name: "Monaco, Juan",\n desc: "6-4, 6-0"\n },\n children: [\n {\n text: { \n name: "Klizan, Martin",\n title: 7\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/slo.jpg",\n HTMLclass: "first-draw"\n },\n {\n text: { \n name: "Monaco, Juan",\n title: 8\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/arg.jpg",\n HTMLclass: "first-draw"\n }\n ]\n }\n ]\n }\n ]\n },\n {\n text: {\n name: "Nieminen, Jarkko",\n desc: "6-3, 1-6, 7-6(3)"\n },\n children: [\n {\n text: {\n name: "Nieminen, Jarkko",\n desc: "4-6, 6-1, 6-4"\n },\n children: [\n {\n text: {\n name: "Raonic, Milos",\n desc: "6-1, 6-4"\n },\n children: [\n {\n text: { \n name: "Raonic, Milos",\n title: 9\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/can.jpg",\n HTMLclass: "first-draw"\n },\n {\n text: { \n name: "Benneteau, Julien",\n title: 10\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/fra.jpg",\n HTMLclass: "first-draw"\n }\n ]\n },\n {\n text: {\n name: "Nieminen, Jarkko",\n desc: "6-1, 6-2"\n },\n children: [\n {\n text: { \n name: "Nieminen, Jarkko",\n title: 11\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/fin.jpg",\n HTMLclass: "first-draw"\n },\n {\n text: { \n name: "Troicki, Viktor",\n title: 12\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/srb.jpg",\n HTMLclass: "first-draw"\n }\n ]\n }\n ]\n },\n {\n text: {\n name: "Del Potro, Juan Martin",\n desc: "6-2, 6-4"\n },\n children: [\n {\n text: {\n name: "Dolgopolov, Alexandr",\n desc: "4-6, 6-2, 6-3"\n },\n children: [\n {\n text: { \n name: "Dolgopolov, Alexandr",\n title: 13\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/ukr.jpg",\n HTMLclass: "first-draw"\n },\n {\n text: {\n name: "Tomic, Bernard",\n title: 14\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/aus.jpg",\n HTMLclass: "first-draw"\n }\n ]\n },\n {\n text: {\n name: "Del Potro, Juan Martin",\n desc: "6-4, 6-0"\n },\n children: [\n {\n text: {\n name: "Bye",\n title: 15\n },\n HTMLclass: "first-draw bye"\n },\n {\n text: {\n name: "Del Potro, Juan Martin",\n title: 16\n },\n image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/arg.jpg",\n HTMLclass: "first-draw"\n }\n ]\n }\n ]\n }\n ]\n }\n ]\n }\n};\n\nnew Treant( tree_structure );\n') # ## Wrap treant-js into a Python library # # We would to produce a function with the following signature: # In[4]: def display_treant(json, css): pass # First issue: the javascript is hosted on a website which means the notebook will not work offline unless we import the javascript at a specific location. See [Jupyter notebook extensions](https://github.com/ipython-contrib/IPython-notebook-extensions) to see where to place them. # In[5]: css = """ .chart { height: 600px; width: 900px; margin: 5px; margin: 15px auto; border: 3px solid #DDD; border-radius: 3px; } .tennis-draw { font-size: 10px; width: 100px; } .tennis-draw.winner { height: 38px; } .tennis-draw.winner:hover { background: url('http://fperucic.github.io/treant-js/examples/tennis-draw/trophy.png') right 0 no-repeat; } .tennis-draw.winner .node-name { padding-left: 10px; margin-top: 1px; display: block; } .tennis-draw .node-name { padding: 2px; white-space: pre; color: #00AFF0; } .tennis-draw .node-desc { padding: 2px; color: #999; } .tennis-draw.first-draw .node-title, .tennis-draw.first-draw .node-name, .tennis-draw.first-draw img { position: absolute; top: -8px; } .tennis-draw.first-draw:hover img { width: 20px; top: -12px; } .tennis-draw.first-draw { width: 165px; height: 20px; } .tennis-draw.first-draw img { margin: 3px 4px 0 0; left: 25px; } .tennis-draw.first-draw .node-title { margin-top: 3px; } .tennis-draw.first-draw .node-name { width: 113px; padding-left: 50px; } .tennis-draw.first-draw.bye .node-name { color: #999; } """ classname = "chart" # this part should be part of a nice API (to avoid trick like this __DIVID__) json_tree = """{ container: "#__DIVID__", levelSeparation: 20, siblingSeparation: 15, subTeeSeparation: 15, rootOrientation: "EAST", node: { HTMLclass: "tennis-draw", drawLineThrough: true }, connectors: { type: "straight", style: { "stroke-width": 2, "stroke": "#ccc" } } }""" # there should a nice API to define that json_data = """{ text: { name: {val: "Djokovic, Novak", href: "http://www.atpworldtour.com/Tennis/Players/Top-Players/Novak-Djokovic.aspx"} }, HTMLclass: "winner", children: [ { text: { name: "Djokovic, Novak", desc: "4-6, 6-2, 6-2" }, children: [ { text: { name: "Djokovic, Novak", desc: "4-6, 6-1, 6-4" }, children: [ { text: { name: "Djokovic, Novak", desc: "4-6, 6-1, 6-4" }, children: [ { text: { name: "Djokovic, Novak", title: 1 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/srb.jpg", HTMLclass: "first-draw", }, { text: { name: "Bye", title: 2 }, HTMLclass: "first-draw bye" } ] }, { text: { name: "Youzhny, Mikhail", desc: "6-4, 6-0" }, children: [ { text: { name: "Youzhny, Mikhail", title: 3 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/rus.jpg", HTMLclass: "first-draw" }, { text: { name: "Gimeno-Traver, Daniel", title: 4 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/esp.jpg", HTMLclass: "first-draw" } ] } ] }, { text: { name: "Monaco, Juan", desc: "6-0, 3-6, 6-3" }, children: [ { text: { name: "Gulbis, Ernests", desc: "4-6, 6-2, 6-3" }, children: [ { text: { name: "Gulbis, Ernests", title: 5 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/lat.jpg", HTMLclass: "first-draw" }, { text: { name: "Isner, John", title: 6 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/usa.jpg", HTMLclass: "first-draw" } ] }, { text: { name: "Monaco, Juan", desc: "6-4, 6-0" }, children: [ { text: { name: "Klizan, Martin", title: 7 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/slo.jpg", HTMLclass: "first-draw" }, { text: { name: "Monaco, Juan", title: 8 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/arg.jpg", HTMLclass: "first-draw" } ] } ] } ] }, { text: { name: "Nieminen, Jarkko", desc: "6-3, 1-6, 7-6(3)" }, children: [ { text: { name: "Nieminen, Jarkko", desc: "4-6, 6-1, 6-4" }, children: [ { text: { name: "Raonic, Milos", desc: "6-1, 6-4" }, children: [ { text: { name: "Raonic, Milos", title: 9 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/can.jpg", HTMLclass: "first-draw" }, { text: { name: "Benneteau, Julien", title: 10 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/fra.jpg", HTMLclass: "first-draw" } ] }, { text: { name: "Nieminen, Jarkko", desc: "6-1, 6-2" }, children: [ { text: { name: "Nieminen, Jarkko", title: 11 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/fin.jpg", HTMLclass: "first-draw" }, { text: { name: "Troicki, Viktor", title: 12 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/srb.jpg", HTMLclass: "first-draw" } ] } ] }, { text: { name: "Del Potro, Juan Martin", desc: "6-2, 6-4" }, children: [ { text: { name: "Dolgopolov, Alexandr", desc: "4-6, 6-2, 6-3" }, children: [ { text: { name: "Dolgopolov, Alexandr", title: 13 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/ukr.jpg", HTMLclass: "first-draw" }, { text: { name: "Tomic, Bernard", title: 14 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/aus.jpg", HTMLclass: "first-draw" } ] }, { text: { name: "Del Potro, Juan Martin", desc: "6-4, 6-0" }, children: [ { text: { name: "Bye", title: 15 }, HTMLclass: "first-draw bye" }, { text: { name: "Del Potro, Juan Martin", title: 16 }, image: "http://fperucic.github.io/treant-js/examples/tennis-draw/flags/arg.jpg", HTMLclass: "first-draw" } ] } ] } ] } ] }""" # In[6]: from jupytalk.talk_examples.treant_wrapper import display_treant from IPython.core.display import display display(display_treant(json_tree, json_data, css, classname)) # ## What's next? # # * Add local support # * Make the graph stick when the notebook is display again (reload dependencies) # * Change parameter ``json_tree`` for a dictionary with options # * Create an API to create the data in Python and not in Json. # In[7]: