├── .gitignore ├── static ├── 404.jpg ├── style.css └── flare.json ├── config-sample.py ├── templates ├── index.html ├── 404.html ├── table.html ├── login.html ├── map.html ├── map_api.html ├── form.html ├── graph.html └── layout.html ├── schema.sql ├── README.md └── flaskfile.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | database.db 4 | config.py 5 | -------------------------------------------------------------------------------- /static/404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flask-tutorial/flask-for-data-science/HEAD/static/404.jpg -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | /* for fixed navbar: margins and paddings */ 2 | 3 | body { 4 | padding-top: 40px; 5 | padding-bottom: 20px; 6 | } 7 | 8 | .navbar { 9 | margin-bottom: 20px; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /config-sample.py: -------------------------------------------------------------------------------- 1 | # configuration 2 | DATABASE = './database.db' 3 | SECRET_KEY = 'replace with your own secret' 4 | USERNAME = 'admin' 5 | PASSWORD = 'asecret' 6 | APP_NAME = 'Flask for Data Scientists' 7 | MTA_KEY = '' 8 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Main

4 |

This is the main page. find it in index.html.

5 |

Use all your HTML skills here.

6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /schema.sql: -------------------------------------------------------------------------------- 1 | drop table if exists entries; 2 | create table entries ( 3 | id integer primary key autoincrement, 4 | title text not null, 5 | text text not null, 6 | mood integer not null, 7 | lat real null, 8 | long real null 9 | ); 10 | -------------------------------------------------------------------------------- /templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Error 404

4 |

The page could not be found. 404 inspiration

5 | 6 |

404 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Example App 2 | 3 | This is an example web app written with flask. Just enough 4 | code to get you started with collecting data, writing it to a database, 5 | and displaying it again in a table or on a map. 6 | 7 | share and enjoy! 8 | 9 | ### 10 | 11 | copy config-sample.py to config.py and edit it 12 | 13 | create the sqlite-database: 14 | 15 | sqlite3 ./database.db < schema.sql 16 | 17 | start the webserver locally: 18 | 19 | python flaskfile.py 20 | 21 | or, if you are deploying to a real webserver, set up wsgi: 22 | 23 | import sys 24 | path = '..../flask-for-data-science' 25 | 26 | if path not in sys.path: 27 | sys.path.insert(0, path) 28 | 29 | from flaskfile import app as application 30 | 31 | -------------------------------------------------------------------------------- /templates/table.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Table

4 |

Display the Data from our database in a table.

5 | 6 | {% if entries|count == 0 %} 7 |

Unbelievable. No entries here so far. entries is {{entries}}

8 | {% else %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% for entry in entries %} 17 | 18 | 19 | 20 | 21 | 22 | 23 | {% endfor %} 24 |
TitleTextMoodPosition
{{ entry[0] }}{{ entry[1] }}{{ entry[2] }}{{ entry[3] }}, {{ entry[4] }}
25 | {% endif %} 26 | 27 | {% endblock %} 28 | 29 | -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Login

4 | {% if error %}

Error: {{ error }}{% endif %} 5 |

6 |
7 | 8 | 9 |
10 |
11 | 12 | 13 |
14 | 15 |
16 | {% endblock %} 17 | 18 | -------------------------------------------------------------------------------- /templates/map.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Table

4 |

Display the Data from our database in a Map.

5 | 6 | {% if entries|count == 0 %} 7 |

Unbelievable. No entries here so far. entries is {{entries}}

8 | {% else %} 9 |
10 | {% endif %} 11 | 12 | {% endblock %} 13 | 14 | {% block javascript %} 15 | 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /templates/map_api.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Table

4 |

Display the Data from the MTA-API in a Map.

5 | 6 |

Choose your Bus: 7 | B26 | 8 | B54 | 9 | B61 | 10 | B69 11 | 12 | {% if entries|count == 0 %} 13 |

Unbelievable. No entries here so far.

14 | {% else %} 15 |
16 | {% endif %} 17 | 18 | {% endblock %} 19 | 20 | {% block javascript %} 21 | 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /templates/form.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |

Form

4 |

The Data you enter here will be saved in a database on our server

5 | {% if error %}

Error: {{ error }}{% endif %} 6 |

7 |
8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 | 35 |
36 | {% endblock %} 37 | 38 | {% block javascript %} 39 | 50 | {% endblock %} 51 | -------------------------------------------------------------------------------- /templates/graph.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 | 16 |

Graph

17 |

Display some Data using d3

18 | {% endblock %} 19 | 20 | {% block javascript %} 21 | 22 | 23 | 139 | {% endblock %} 140 | -------------------------------------------------------------------------------- /templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ config.APP_NAME }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 48 | 49 |
50 | {% for message in get_flashed_messages() %} 51 |
52 | 53 | {{ message }} 54 |
55 | {% endfor %} 56 | {% block body %}{% endblock %} 57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 84 | {% block javascript %}{% endblock %} 85 | 86 | 87 | -------------------------------------------------------------------------------- /flaskfile.py: -------------------------------------------------------------------------------- 1 | # ==================================================================================== 2 | # Example Flask Web App for Data Scientist 3 | # ==================================================================================== 4 | # originially from https://github.com/flask-tutorial/flask-for-data-science 5 | 6 | # all the imports 7 | import sqlite3, urllib, json, os 8 | from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash 9 | 10 | app = Flask(__name__) 11 | 12 | # this will read in variables from config.py 13 | app.config.from_object("config") 14 | 15 | 16 | # ==================================================================================== 17 | # setup and teardown for each HTTP request 18 | # ==================================================================================== 19 | # the @ sign here means that app.before_request is a "decorator" for the function 20 | # defined in the next line. http://legacy.python.org/dev/peps/pep-0318/#current-syntax 21 | # but you don't have to understand that to use it 22 | # 23 | # in a flask app, putting @app.before_request before a function means 24 | # that this function will be called before a request is routed, and app.teardown_request 25 | # is called after everything is finished. 26 | # So this is a good place to connect/disconnect to the database 27 | @app.before_request 28 | def before_request(): 29 | g.dir = os.path.dirname(os.path.abspath(__file__)) 30 | g.db = sqlite3.connect(g.dir + '/' + app.config['DATABASE']) 31 | 32 | @app.teardown_request 33 | def teardown_request(exception): 34 | db = getattr(g, 'db', None) 35 | if db is not None: 36 | db.close() 37 | 38 | # ==================================================================================== 39 | # routes - these map URLs to your python functions 40 | # ==================================================================================== 41 | @app.route('/') 42 | def index(): 43 | return render_template('index.html') 44 | 45 | @app.route('/add', methods=['POST']) 46 | def add_entry(): 47 | if not session.get('logged_in'): 48 | abort(401) 49 | flash('New entry was successfully posted') 50 | return redirect(url_for('table')) 51 | 52 | @app.route('/form', methods=['GET', 'POST']) 53 | def form(): 54 | errors = [] 55 | if request.method == 'POST': 56 | title = request.form.get('title') 57 | if len(title) < 3: 58 | errors.append( 'Please choose a title (at least 3 letters long)' ) 59 | 60 | text = request.form.get('text') 61 | if len(text) < 10: 62 | errors.append( 'please write the text (at least 10 letters long)' ) 63 | 64 | mood = int( request.form.get('mood') ) 65 | if not mood in [1,2,3,4,5]: 66 | errors.append( 'please choose a mood' ) 67 | 68 | if len(errors) == 0: 69 | g.db.execute('insert into entries (title, text, mood, lat, long) values (?, ?, ?, ?, ?)', 70 | [title, text, mood, request.form.get('lat'), request.form.get('long')]) 71 | g.db.commit() 72 | flash('Your entry "' + text + '" was saved to the database') 73 | return redirect( url_for('index') ) 74 | return render_template('form.html', error=", ".join(errors)) 75 | 76 | @app.route('/table') 77 | def table(): 78 | cur = g.db.execute('select title, text, mood, lat, long from entries order by id desc') 79 | entries = cur.fetchall() 80 | return render_template('table.html', entries=entries) 81 | 82 | @app.route('/graph') 83 | def graph(): 84 | return render_template('graph.html') 85 | 86 | @app.route('/map') 87 | def map(): 88 | cur = g.db.execute('select title, text, mood, lat, long from entries order by id desc') 89 | entries = cur.fetchall() 90 | return render_template('map.html', entries=entries) 91 | 92 | @app.route('/map_api') 93 | def map_api(): 94 | busline = request.args.get('busline') 95 | if not busline in ['B26', 'B54', 'B61', 'B69']: 96 | busline = 'B26' 97 | url = 'http://api.prod.obanyc.com/api/siri/vehicle-monitoring.json?key=%s&VehicleMonitoringDetailLevel=calls&LineRef=%s' % (app.config['MTA_KEY'], busline) 98 | json_data = urllib.urlopen(url).read() 99 | bus_data = json.loads( json_data )['Siri']['ServiceDelivery']['VehicleMonitoringDelivery'][0] 100 | entries = [] 101 | if( not 'ErrorCondition' in bus_data.keys() ): 102 | bus_data = bus_data['VehicleActivity'] 103 | for bus in bus_data: 104 | location = bus['MonitoredVehicleJourney']['VehicleLocation'] 105 | entries.append( location ) 106 | app.logger.info('Found %d busses on line %s' % (len(entries), busline)) 107 | return render_template('map_api.html', entries=entries) 108 | 109 | @app.route('/login', methods=['GET', 'POST']) 110 | def login(): 111 | error = None 112 | if request.method == 'POST': 113 | if request.form['username'] != app.config['USERNAME']: 114 | error = 'Invalid username' 115 | elif request.form['password'] != app.config['PASSWORD']: 116 | error = 'Invalid password' 117 | else: 118 | session['logged_in'] = True 119 | session['username'] = request.form['username'] 120 | flash('You were logged in as ' + session['username']) 121 | return redirect( url_for('index') ) 122 | return render_template('login.html', error=error) 123 | 124 | @app.route('/logout') 125 | def logout(): 126 | session.pop('logged_in', None) 127 | flash('You were logged out') 128 | return redirect(url_for('index')) 129 | 130 | # ==================================================================================== 131 | @app.errorhandler(404) 132 | def page_not_found(e): 133 | return render_template('404.html'), 404 134 | 135 | # ==================================================================================== 136 | if __name__ == '__main__': 137 | app.run() 138 | # ==================================================================================== 139 | -------------------------------------------------------------------------------- /static/flare.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flare", 3 | "children": [ 4 | { 5 | "name": "analytics", 6 | "children": [ 7 | { 8 | "name": "cluster", 9 | "children": [ 10 | {"name": "AgglomerativeCluster", "size": 3938}, 11 | {"name": "CommunityStructure", "size": 3812}, 12 | {"name": "HierarchicalCluster", "size": 6714}, 13 | {"name": "MergeEdge", "size": 743} 14 | ] 15 | }, 16 | { 17 | "name": "graph", 18 | "children": [ 19 | {"name": "BetweennessCentrality", "size": 3534}, 20 | {"name": "LinkDistance", "size": 5731}, 21 | {"name": "MaxFlowMinCut", "size": 7840}, 22 | {"name": "ShortestPaths", "size": 5914}, 23 | {"name": "SpanningTree", "size": 3416} 24 | ] 25 | }, 26 | { 27 | "name": "optimization", 28 | "children": [ 29 | {"name": "AspectRatioBanker", "size": 7074} 30 | ] 31 | } 32 | ] 33 | }, 34 | { 35 | "name": "animate", 36 | "children": [ 37 | {"name": "Easing", "size": 17010}, 38 | {"name": "FunctionSequence", "size": 5842}, 39 | { 40 | "name": "interpolate", 41 | "children": [ 42 | {"name": "ArrayInterpolator", "size": 1983}, 43 | {"name": "ColorInterpolator", "size": 2047}, 44 | {"name": "DateInterpolator", "size": 1375}, 45 | {"name": "Interpolator", "size": 8746}, 46 | {"name": "MatrixInterpolator", "size": 2202}, 47 | {"name": "NumberInterpolator", "size": 1382}, 48 | {"name": "ObjectInterpolator", "size": 1629}, 49 | {"name": "PointInterpolator", "size": 1675}, 50 | {"name": "RectangleInterpolator", "size": 2042} 51 | ] 52 | }, 53 | {"name": "ISchedulable", "size": 1041}, 54 | {"name": "Parallel", "size": 5176}, 55 | {"name": "Pause", "size": 449}, 56 | {"name": "Scheduler", "size": 5593}, 57 | {"name": "Sequence", "size": 5534}, 58 | {"name": "Transition", "size": 9201}, 59 | {"name": "Transitioner", "size": 19975}, 60 | {"name": "TransitionEvent", "size": 1116}, 61 | {"name": "Tween", "size": 6006} 62 | ] 63 | }, 64 | { 65 | "name": "data", 66 | "children": [ 67 | { 68 | "name": "converters", 69 | "children": [ 70 | {"name": "Converters", "size": 721}, 71 | {"name": "DelimitedTextConverter", "size": 4294}, 72 | {"name": "GraphMLConverter", "size": 9800}, 73 | {"name": "IDataConverter", "size": 1314}, 74 | {"name": "JSONConverter", "size": 2220} 75 | ] 76 | }, 77 | {"name": "DataField", "size": 1759}, 78 | {"name": "DataSchema", "size": 2165}, 79 | {"name": "DataSet", "size": 586}, 80 | {"name": "DataSource", "size": 3331}, 81 | {"name": "DataTable", "size": 772}, 82 | {"name": "DataUtil", "size": 3322} 83 | ] 84 | }, 85 | { 86 | "name": "display", 87 | "children": [ 88 | {"name": "DirtySprite", "size": 8833}, 89 | {"name": "LineSprite", "size": 1732}, 90 | {"name": "RectSprite", "size": 3623}, 91 | {"name": "TextSprite", "size": 10066} 92 | ] 93 | }, 94 | { 95 | "name": "flex", 96 | "children": [ 97 | {"name": "FlareVis", "size": 4116} 98 | ] 99 | }, 100 | { 101 | "name": "physics", 102 | "children": [ 103 | {"name": "DragForce", "size": 1082}, 104 | {"name": "GravityForce", "size": 1336}, 105 | {"name": "IForce", "size": 319}, 106 | {"name": "NBodyForce", "size": 10498}, 107 | {"name": "Particle", "size": 2822}, 108 | {"name": "Simulation", "size": 9983}, 109 | {"name": "Spring", "size": 2213}, 110 | {"name": "SpringForce", "size": 1681} 111 | ] 112 | }, 113 | { 114 | "name": "query", 115 | "children": [ 116 | {"name": "AggregateExpression", "size": 1616}, 117 | {"name": "And", "size": 1027}, 118 | {"name": "Arithmetic", "size": 3891}, 119 | {"name": "Average", "size": 891}, 120 | {"name": "BinaryExpression", "size": 2893}, 121 | {"name": "Comparison", "size": 5103}, 122 | {"name": "CompositeExpression", "size": 3677}, 123 | {"name": "Count", "size": 781}, 124 | {"name": "DateUtil", "size": 4141}, 125 | {"name": "Distinct", "size": 933}, 126 | {"name": "Expression", "size": 5130}, 127 | {"name": "ExpressionIterator", "size": 3617}, 128 | {"name": "Fn", "size": 3240}, 129 | {"name": "If", "size": 2732}, 130 | {"name": "IsA", "size": 2039}, 131 | {"name": "Literal", "size": 1214}, 132 | {"name": "Match", "size": 3748}, 133 | {"name": "Maximum", "size": 843}, 134 | { 135 | "name": "methods", 136 | "children": [ 137 | {"name": "add", "size": 593}, 138 | {"name": "and", "size": 330}, 139 | {"name": "average", "size": 287}, 140 | {"name": "count", "size": 277}, 141 | {"name": "distinct", "size": 292}, 142 | {"name": "div", "size": 595}, 143 | {"name": "eq", "size": 594}, 144 | {"name": "fn", "size": 460}, 145 | {"name": "gt", "size": 603}, 146 | {"name": "gte", "size": 625}, 147 | {"name": "iff", "size": 748}, 148 | {"name": "isa", "size": 461}, 149 | {"name": "lt", "size": 597}, 150 | {"name": "lte", "size": 619}, 151 | {"name": "max", "size": 283}, 152 | {"name": "min", "size": 283}, 153 | {"name": "mod", "size": 591}, 154 | {"name": "mul", "size": 603}, 155 | {"name": "neq", "size": 599}, 156 | {"name": "not", "size": 386}, 157 | {"name": "or", "size": 323}, 158 | {"name": "orderby", "size": 307}, 159 | {"name": "range", "size": 772}, 160 | {"name": "select", "size": 296}, 161 | {"name": "stddev", "size": 363}, 162 | {"name": "sub", "size": 600}, 163 | {"name": "sum", "size": 280}, 164 | {"name": "update", "size": 307}, 165 | {"name": "variance", "size": 335}, 166 | {"name": "where", "size": 299}, 167 | {"name": "xor", "size": 354}, 168 | {"name": "_", "size": 264} 169 | ] 170 | }, 171 | {"name": "Minimum", "size": 843}, 172 | {"name": "Not", "size": 1554}, 173 | {"name": "Or", "size": 970}, 174 | {"name": "Query", "size": 13896}, 175 | {"name": "Range", "size": 1594}, 176 | {"name": "StringUtil", "size": 4130}, 177 | {"name": "Sum", "size": 791}, 178 | {"name": "Variable", "size": 1124}, 179 | {"name": "Variance", "size": 1876}, 180 | {"name": "Xor", "size": 1101} 181 | ] 182 | }, 183 | { 184 | "name": "scale", 185 | "children": [ 186 | {"name": "IScaleMap", "size": 2105}, 187 | {"name": "LinearScale", "size": 1316}, 188 | {"name": "LogScale", "size": 3151}, 189 | {"name": "OrdinalScale", "size": 3770}, 190 | {"name": "QuantileScale", "size": 2435}, 191 | {"name": "QuantitativeScale", "size": 4839}, 192 | {"name": "RootScale", "size": 1756}, 193 | {"name": "Scale", "size": 4268}, 194 | {"name": "ScaleType", "size": 1821}, 195 | {"name": "TimeScale", "size": 5833} 196 | ] 197 | }, 198 | { 199 | "name": "util", 200 | "children": [ 201 | {"name": "Arrays", "size": 8258}, 202 | {"name": "Colors", "size": 10001}, 203 | {"name": "Dates", "size": 8217}, 204 | {"name": "Displays", "size": 12555}, 205 | {"name": "Filter", "size": 2324}, 206 | {"name": "Geometry", "size": 10993}, 207 | { 208 | "name": "heap", 209 | "children": [ 210 | {"name": "FibonacciHeap", "size": 9354}, 211 | {"name": "HeapNode", "size": 1233} 212 | ] 213 | }, 214 | {"name": "IEvaluable", "size": 335}, 215 | {"name": "IPredicate", "size": 383}, 216 | {"name": "IValueProxy", "size": 874}, 217 | { 218 | "name": "math", 219 | "children": [ 220 | {"name": "DenseMatrix", "size": 3165}, 221 | {"name": "IMatrix", "size": 2815}, 222 | {"name": "SparseMatrix", "size": 3366} 223 | ] 224 | }, 225 | {"name": "Maths", "size": 17705}, 226 | {"name": "Orientation", "size": 1486}, 227 | { 228 | "name": "palette", 229 | "children": [ 230 | {"name": "ColorPalette", "size": 6367}, 231 | {"name": "Palette", "size": 1229}, 232 | {"name": "ShapePalette", "size": 2059}, 233 | {"name": "SizePalette", "size": 2291} 234 | ] 235 | }, 236 | {"name": "Property", "size": 5559}, 237 | {"name": "Shapes", "size": 19118}, 238 | {"name": "Sort", "size": 6887}, 239 | {"name": "Stats", "size": 6557}, 240 | {"name": "Strings", "size": 22026} 241 | ] 242 | }, 243 | { 244 | "name": "vis", 245 | "children": [ 246 | { 247 | "name": "axis", 248 | "children": [ 249 | {"name": "Axes", "size": 1302}, 250 | {"name": "Axis", "size": 24593}, 251 | {"name": "AxisGridLine", "size": 652}, 252 | {"name": "AxisLabel", "size": 636}, 253 | {"name": "CartesianAxes", "size": 6703} 254 | ] 255 | }, 256 | { 257 | "name": "controls", 258 | "children": [ 259 | {"name": "AnchorControl", "size": 2138}, 260 | {"name": "ClickControl", "size": 3824}, 261 | {"name": "Control", "size": 1353}, 262 | {"name": "ControlList", "size": 4665}, 263 | {"name": "DragControl", "size": 2649}, 264 | {"name": "ExpandControl", "size": 2832}, 265 | {"name": "HoverControl", "size": 4896}, 266 | {"name": "IControl", "size": 763}, 267 | {"name": "PanZoomControl", "size": 5222}, 268 | {"name": "SelectionControl", "size": 7862}, 269 | {"name": "TooltipControl", "size": 8435} 270 | ] 271 | }, 272 | { 273 | "name": "data", 274 | "children": [ 275 | {"name": "Data", "size": 20544}, 276 | {"name": "DataList", "size": 19788}, 277 | {"name": "DataSprite", "size": 10349}, 278 | {"name": "EdgeSprite", "size": 3301}, 279 | {"name": "NodeSprite", "size": 19382}, 280 | { 281 | "name": "render", 282 | "children": [ 283 | {"name": "ArrowType", "size": 698}, 284 | {"name": "EdgeRenderer", "size": 5569}, 285 | {"name": "IRenderer", "size": 353}, 286 | {"name": "ShapeRenderer", "size": 2247} 287 | ] 288 | }, 289 | {"name": "ScaleBinding", "size": 11275}, 290 | {"name": "Tree", "size": 7147}, 291 | {"name": "TreeBuilder", "size": 9930} 292 | ] 293 | }, 294 | { 295 | "name": "events", 296 | "children": [ 297 | {"name": "DataEvent", "size": 2313}, 298 | {"name": "SelectionEvent", "size": 1880}, 299 | {"name": "TooltipEvent", "size": 1701}, 300 | {"name": "VisualizationEvent", "size": 1117} 301 | ] 302 | }, 303 | { 304 | "name": "legend", 305 | "children": [ 306 | {"name": "Legend", "size": 20859}, 307 | {"name": "LegendItem", "size": 4614}, 308 | {"name": "LegendRange", "size": 10530} 309 | ] 310 | }, 311 | { 312 | "name": "operator", 313 | "children": [ 314 | { 315 | "name": "distortion", 316 | "children": [ 317 | {"name": "BifocalDistortion", "size": 4461}, 318 | {"name": "Distortion", "size": 6314}, 319 | {"name": "FisheyeDistortion", "size": 3444} 320 | ] 321 | }, 322 | { 323 | "name": "encoder", 324 | "children": [ 325 | {"name": "ColorEncoder", "size": 3179}, 326 | {"name": "Encoder", "size": 4060}, 327 | {"name": "PropertyEncoder", "size": 4138}, 328 | {"name": "ShapeEncoder", "size": 1690}, 329 | {"name": "SizeEncoder", "size": 1830} 330 | ] 331 | }, 332 | { 333 | "name": "filter", 334 | "children": [ 335 | {"name": "FisheyeTreeFilter", "size": 5219}, 336 | {"name": "GraphDistanceFilter", "size": 3165}, 337 | {"name": "VisibilityFilter", "size": 3509} 338 | ] 339 | }, 340 | {"name": "IOperator", "size": 1286}, 341 | { 342 | "name": "label", 343 | "children": [ 344 | {"name": "Labeler", "size": 9956}, 345 | {"name": "RadialLabeler", "size": 3899}, 346 | {"name": "StackedAreaLabeler", "size": 3202} 347 | ] 348 | }, 349 | { 350 | "name": "layout", 351 | "children": [ 352 | {"name": "AxisLayout", "size": 6725}, 353 | {"name": "BundledEdgeRouter", "size": 3727}, 354 | {"name": "CircleLayout", "size": 9317}, 355 | {"name": "CirclePackingLayout", "size": 12003}, 356 | {"name": "DendrogramLayout", "size": 4853}, 357 | {"name": "ForceDirectedLayout", "size": 8411}, 358 | {"name": "IcicleTreeLayout", "size": 4864}, 359 | {"name": "IndentedTreeLayout", "size": 3174}, 360 | {"name": "Layout", "size": 7881}, 361 | {"name": "NodeLinkTreeLayout", "size": 12870}, 362 | {"name": "PieLayout", "size": 2728}, 363 | {"name": "RadialTreeLayout", "size": 12348}, 364 | {"name": "RandomLayout", "size": 870}, 365 | {"name": "StackedAreaLayout", "size": 9121}, 366 | {"name": "TreeMapLayout", "size": 9191} 367 | ] 368 | }, 369 | {"name": "Operator", "size": 2490}, 370 | {"name": "OperatorList", "size": 5248}, 371 | {"name": "OperatorSequence", "size": 4190}, 372 | {"name": "OperatorSwitch", "size": 2581}, 373 | {"name": "SortOperator", "size": 2023} 374 | ] 375 | }, 376 | {"name": "Visualization", "size": 16540} 377 | ] 378 | } 379 | ] 380 | } --------------------------------------------------------------------------------