Show More
This diff has been collapsed as it changes many lines, (577 lines changed) Show them Hide them | |||
@@ -11,114 +11,35 b'' | |||
|
11 | 11 | "cell_type": "code", |
|
12 | 12 | "collapsed": false, |
|
13 | 13 | "input": [ |
|
14 | "from __future__ import print_function # py 2.7 compat" | |
|
15 | ], | |
|
16 | "language": "python", | |
|
17 | "metadata": {}, | |
|
18 | "outputs": [], | |
|
19 | "prompt_number": 1 | |
|
20 | }, | |
|
21 | { | |
|
22 | "cell_type": "heading", | |
|
23 | "level": 1, | |
|
24 | "metadata": {}, | |
|
25 | "source": [ | |
|
26 | "Validate NetworkX version" | |
|
27 | ] | |
|
28 | }, | |
|
29 | { | |
|
30 | "cell_type": "code", | |
|
31 | "collapsed": false, | |
|
32 | "input": [ | |
|
33 | "import networkx as nx\n", | |
|
34 | "version = float('.'.join(nx.__version__.split('.')[0:2]))\n", | |
|
35 | "if version < 1.8:\n", | |
|
36 | " raise Exception('This notebook requires networkx version 1.8 or later. Version %s is installed on this machine.' % nx.__version__)" | |
|
37 | ], | |
|
38 | "language": "python", | |
|
39 | "metadata": {}, | |
|
40 | "outputs": [], | |
|
41 | "prompt_number": 2 | |
|
42 | }, | |
|
43 | { | |
|
44 | "cell_type": "heading", | |
|
45 | "level": 1, | |
|
46 | "metadata": {}, | |
|
47 | "source": [ | |
|
48 | "Simple Output Test" | |
|
49 | ] | |
|
50 | }, | |
|
51 | { | |
|
52 | "cell_type": "code", | |
|
53 | "collapsed": false, | |
|
54 | "input": [ | |
|
55 | "from networkx.readwrite import json_graph\n", | |
|
56 | "import json\n", | |
|
14 | "from __future__ import print_function # py 2.7 compat\n", | |
|
57 | 15 | "\n", |
|
58 | "def to_d3_json(graph):\n", | |
|
59 | " data = json_graph.node_link_data(graph)\n", | |
|
60 | " return json.dumps(data)" | |
|
16 | "import networkx as nx" | |
|
61 | 17 | ], |
|
62 | 18 | "language": "python", |
|
63 | 19 | "metadata": {}, |
|
64 | 20 | "outputs": [], |
|
65 | "prompt_number": 3 | |
|
66 | }, | |
|
67 | { | |
|
68 | "cell_type": "code", | |
|
69 | "collapsed": false, | |
|
70 | "input": [ | |
|
71 | "G = nx.Graph([(1,2)])\n", | |
|
72 | "to_d3_json(G)" | |
|
73 | ], | |
|
74 | "language": "python", | |
|
75 | "metadata": {}, | |
|
76 | "outputs": [ | |
|
77 | { | |
|
78 | "metadata": {}, | |
|
79 | "output_type": "pyout", | |
|
80 | "prompt_number": 4, | |
|
81 | "text": [ | |
|
82 | "'{\"multigraph\": false, \"directed\": false, \"links\": [{\"target\": 1, \"source\": 0}], \"graph\": [], \"nodes\": [{\"id\": 1}, {\"id\": 2}]}'" | |
|
83 | ] | |
|
84 | } | |
|
85 | ], | |
|
86 | 21 | "prompt_number": 4 |
|
87 | 22 | }, |
|
88 | 23 | { |
|
89 |
"cell_type": " |
|
|
90 | "collapsed": false, | |
|
91 | "input": [ | |
|
92 | "G.add_node('test')\n", | |
|
93 | "to_d3_json(G)" | |
|
94 | ], | |
|
95 | "language": "python", | |
|
96 | "metadata": {}, | |
|
97 | "outputs": [ | |
|
98 | { | |
|
24 | "cell_type": "markdown", | |
|
99 | 25 |
|
|
100 | "output_type": "pyout", | |
|
101 | "prompt_number": 5, | |
|
102 | "text": [ | |
|
103 | "'{\"multigraph\": false, \"directed\": false, \"links\": [{\"target\": 1, \"source\": 0}], \"graph\": [], \"nodes\": [{\"id\": 1}, {\"id\": 2}, {\"id\": \"test\"}]}'" | |
|
26 | "source": [ | |
|
27 | "This notebook demonstrates how NetworkX and D3 can be married using custom widget code." | |
|
104 | 28 |
|
|
105 | } | |
|
106 | ], | |
|
107 | "prompt_number": 5 | |
|
108 | 29 | }, |
|
109 | 30 | { |
|
110 | 31 | "cell_type": "heading", |
|
111 | 32 | "level": 1, |
|
112 | 33 | "metadata": {}, |
|
113 | 34 | "source": [ |
|
114 | "Listen To Graph Changes" | |
|
35 | "Hooking NetworkX Graphs" | |
|
115 | 36 | ] |
|
116 | 37 | }, |
|
117 | 38 | { |
|
118 | 39 | "cell_type": "markdown", |
|
119 | 40 | "metadata": {}, |
|
120 | 41 | "source": [ |
|
121 | "Create a simple eventfull dictionary." | |
|
42 | "NetworkX graphs do not have events that can be listened to. In order to watch the NetworkX graph object for changes a custom eventful graph object must be created. The custom eventful graph object will inherit from the base graph object and use special eventful dictionaries instead of standard Python dict instances. Because NetworkX nests dictionaries inside dictionaries, it's important that the eventful dictionary is capable of recognizing when a dictionary value is set to another dictionary instance. When this happens, the eventful dictionary needs to also make the new dictionary an eventful dictionary. This allows the eventful dictionary to listen to changes made to dictionaries within dictionaries." | |
|
122 | 43 | ] |
|
123 | 44 | }, |
|
124 | 45 | { |
@@ -212,255 +133,12 b'' | |||
|
212 | 133 | " \n", |
|
213 | 134 | " def clear(self):\n", |
|
214 | 135 | " for key in list(self.keys()):\n", |
|
215 |
" del self[key] |
|
|
216 | ], | |
|
217 | "language": "python", | |
|
218 | "metadata": {}, | |
|
219 | "outputs": [], | |
|
220 | "prompt_number": 6 | |
|
221 | }, | |
|
222 | { | |
|
223 | "cell_type": "markdown", | |
|
224 | "metadata": {}, | |
|
225 | "source": [ | |
|
226 | "Test the eventful dictionary." | |
|
227 | ] | |
|
228 | }, | |
|
229 | { | |
|
230 | "cell_type": "code", | |
|
231 | "collapsed": false, | |
|
232 | "input": [ | |
|
233 | "a = EventfulDict()" | |
|
234 | ], | |
|
235 | "language": "python", | |
|
236 | "metadata": {}, | |
|
237 | "outputs": [], | |
|
238 | "prompt_number": 7 | |
|
239 | }, | |
|
240 | { | |
|
241 | "cell_type": "code", | |
|
242 | "collapsed": false, | |
|
243 | "input": [ | |
|
244 | "def echo_dict_events(eventful_dict, prefix=''):\n", | |
|
245 | " def key_add(key, value):\n", | |
|
246 | " print(prefix + 'add (%s, %s)' % (key, str(value)))\n", | |
|
247 | " def key_set(key, value):\n", | |
|
248 | " print(prefix + 'set (%s, %s)' % (key, str(value)))\n", | |
|
249 | " def key_del(key):\n", | |
|
250 | " print(prefix + 'del %s' % key)\n", | |
|
251 | " eventful_dict.on_add(key_add)\n", | |
|
252 | " eventful_dict.on_set(key_set)\n", | |
|
253 | " eventful_dict.on_del(key_del)\n", | |
|
254 | " \n", | |
|
255 | "echo_dict_events(a)" | |
|
136 | " del self[key]" | |
|
256 | 137 | ], |
|
257 | 138 | "language": "python", |
|
258 | 139 | "metadata": {}, |
|
259 | 140 | "outputs": [], |
|
260 |
"prompt_number": |
|
|
261 | }, | |
|
262 | { | |
|
263 | "cell_type": "code", | |
|
264 | "collapsed": false, | |
|
265 | "input": [ | |
|
266 | "a['a'] = 'hello'" | |
|
267 | ], | |
|
268 | "language": "python", | |
|
269 | "metadata": {}, | |
|
270 | "outputs": [ | |
|
271 | { | |
|
272 | "output_type": "stream", | |
|
273 | "stream": "stdout", | |
|
274 | "text": [ | |
|
275 | "add (a, hello)\n" | |
|
276 | ] | |
|
277 | } | |
|
278 | ], | |
|
279 | "prompt_number": 9 | |
|
280 | }, | |
|
281 | { | |
|
282 | "cell_type": "code", | |
|
283 | "collapsed": false, | |
|
284 | "input": [ | |
|
285 | "a['a'] = 'goodbye'" | |
|
286 | ], | |
|
287 | "language": "python", | |
|
288 | "metadata": {}, | |
|
289 | "outputs": [ | |
|
290 | { | |
|
291 | "output_type": "stream", | |
|
292 | "stream": "stdout", | |
|
293 | "text": [ | |
|
294 | "set (a, goodbye)\n" | |
|
295 | ] | |
|
296 | } | |
|
297 | ], | |
|
298 | "prompt_number": 10 | |
|
299 | }, | |
|
300 | { | |
|
301 | "cell_type": "code", | |
|
302 | "collapsed": false, | |
|
303 | "input": [ | |
|
304 | "b = {'c': 'yay', 'd': 'no'}\n", | |
|
305 | "a.update(b)" | |
|
306 | ], | |
|
307 | "language": "python", | |
|
308 | "metadata": {}, | |
|
309 | "outputs": [ | |
|
310 | { | |
|
311 | "output_type": "stream", | |
|
312 | "stream": "stdout", | |
|
313 | "text": [ | |
|
314 | "add (c, yay)\n", | |
|
315 | "add (d, no)\n" | |
|
316 | ] | |
|
317 | } | |
|
318 | ], | |
|
319 | "prompt_number": 11 | |
|
320 | }, | |
|
321 | { | |
|
322 | "cell_type": "code", | |
|
323 | "collapsed": false, | |
|
324 | "input": [ | |
|
325 | "a" | |
|
326 | ], | |
|
327 | "language": "python", | |
|
328 | "metadata": {}, | |
|
329 | "outputs": [ | |
|
330 | { | |
|
331 | "metadata": {}, | |
|
332 | "output_type": "pyout", | |
|
333 | "prompt_number": 12, | |
|
334 | "text": [ | |
|
335 | "{'a': 'goodbye', 'c': 'yay', 'd': 'no'}" | |
|
336 | ] | |
|
337 | } | |
|
338 | ], | |
|
339 | "prompt_number": 12 | |
|
340 | }, | |
|
341 | { | |
|
342 | "cell_type": "code", | |
|
343 | "collapsed": false, | |
|
344 | "input": [ | |
|
345 | "a.pop('a')" | |
|
346 | ], | |
|
347 | "language": "python", | |
|
348 | "metadata": {}, | |
|
349 | "outputs": [ | |
|
350 | { | |
|
351 | "metadata": {}, | |
|
352 | "output_type": "pyout", | |
|
353 | "prompt_number": 13, | |
|
354 | "text": [ | |
|
355 | "'goodbye'" | |
|
356 | ] | |
|
357 | } | |
|
358 | ], | |
|
359 | "prompt_number": 13 | |
|
360 | }, | |
|
361 | { | |
|
362 | "cell_type": "code", | |
|
363 | "collapsed": false, | |
|
364 | "input": [ | |
|
365 | "a.popitem()" | |
|
366 | ], | |
|
367 | "language": "python", | |
|
368 | "metadata": {}, | |
|
369 | "outputs": [ | |
|
370 | { | |
|
371 | "output_type": "stream", | |
|
372 | "stream": "stdout", | |
|
373 | "text": [ | |
|
374 | "del c\n" | |
|
375 | ] | |
|
376 | }, | |
|
377 | { | |
|
378 | "metadata": {}, | |
|
379 | "output_type": "pyout", | |
|
380 | "prompt_number": 14, | |
|
381 | "text": [ | |
|
382 | "('c', 'yay')" | |
|
383 | ] | |
|
384 | } | |
|
385 | ], | |
|
386 | "prompt_number": 14 | |
|
387 | }, | |
|
388 | { | |
|
389 | "cell_type": "code", | |
|
390 | "collapsed": false, | |
|
391 | "input": [ | |
|
392 | "a['e'] = {}" | |
|
393 | ], | |
|
394 | "language": "python", | |
|
395 | "metadata": {}, | |
|
396 | "outputs": [ | |
|
397 | { | |
|
398 | "output_type": "stream", | |
|
399 | "stream": "stdout", | |
|
400 | "text": [ | |
|
401 | "add (e, {})\n" | |
|
402 | ] | |
|
403 | } | |
|
404 | ], | |
|
405 | "prompt_number": 15 | |
|
406 | }, | |
|
407 | { | |
|
408 | "cell_type": "code", | |
|
409 | "collapsed": false, | |
|
410 | "input": [ | |
|
411 | "a['e']['a'] = 0" | |
|
412 | ], | |
|
413 | "language": "python", | |
|
414 | "metadata": {}, | |
|
415 | "outputs": [ | |
|
416 | { | |
|
417 | "output_type": "stream", | |
|
418 | "stream": "stdout", | |
|
419 | "text": [ | |
|
420 | "set (e, {'a': 0})\n" | |
|
421 | ] | |
|
422 | } | |
|
423 | ], | |
|
424 | "prompt_number": 16 | |
|
425 | }, | |
|
426 | { | |
|
427 | "cell_type": "code", | |
|
428 | "collapsed": false, | |
|
429 | "input": [ | |
|
430 | "a['e']['b'] = 1" | |
|
431 | ], | |
|
432 | "language": "python", | |
|
433 | "metadata": {}, | |
|
434 | "outputs": [ | |
|
435 | { | |
|
436 | "output_type": "stream", | |
|
437 | "stream": "stdout", | |
|
438 | "text": [ | |
|
439 | "set (e, {'a': 0, 'b': 1})\n" | |
|
440 | ] | |
|
441 | } | |
|
442 | ], | |
|
443 | "prompt_number": 17 | |
|
444 | }, | |
|
445 | { | |
|
446 | "cell_type": "code", | |
|
447 | "collapsed": false, | |
|
448 | "input": [ | |
|
449 | "a.clear()" | |
|
450 | ], | |
|
451 | "language": "python", | |
|
452 | "metadata": {}, | |
|
453 | "outputs": [ | |
|
454 | { | |
|
455 | "output_type": "stream", | |
|
456 | "stream": "stdout", | |
|
457 | "text": [ | |
|
458 | "del e\n", | |
|
459 | "del d\n" | |
|
460 | ] | |
|
461 | } | |
|
462 | ], | |
|
463 | "prompt_number": 18 | |
|
141 | "prompt_number": 5 | |
|
464 | 142 | }, |
|
465 | 143 | { |
|
466 | 144 | "cell_type": "markdown", |
@@ -487,12 +165,30 b'' | |||
|
487 | 165 | "language": "python", |
|
488 | 166 | "metadata": {}, |
|
489 | 167 | "outputs": [], |
|
490 |
"prompt_number": |
|
|
168 | "prompt_number": 6 | |
|
169 | }, | |
|
170 | { | |
|
171 | "cell_type": "markdown", | |
|
172 | "metadata": {}, | |
|
173 | "source": [ | |
|
174 | "To make sure that the eventful graph works, create a new graph and log the dictionary events raised." | |
|
175 | ] | |
|
491 | 176 | }, |
|
492 | 177 | { |
|
493 | 178 | "cell_type": "code", |
|
494 | 179 | "collapsed": false, |
|
495 | 180 | "input": [ |
|
181 | "def echo_dict_events(eventful_dict, prefix=''):\n", | |
|
182 | " def key_add(key, value):\n", | |
|
183 | " print(prefix + 'add (%s, %s)' % (key, str(value)))\n", | |
|
184 | " def key_set(key, value):\n", | |
|
185 | " print(prefix + 'set (%s, %s)' % (key, str(value)))\n", | |
|
186 | " def key_del(key):\n", | |
|
187 | " print(prefix + 'del %s' % key)\n", | |
|
188 | " eventful_dict.on_add(key_add)\n", | |
|
189 | " eventful_dict.on_set(key_set)\n", | |
|
190 | " eventful_dict.on_del(key_del)\n", | |
|
191 | " \n", | |
|
496 | 192 | "def echo_graph_events(eventful_graph):\n", |
|
497 | 193 | " for key in ['graph', 'node', 'adj']:\n", |
|
498 | 194 | " echo_dict_events(getattr(eventful_graph, key), prefix=key+' ')" |
@@ -500,48 +196,18 b'' | |||
|
500 | 196 | "language": "python", |
|
501 | 197 | "metadata": {}, |
|
502 | 198 | "outputs": [], |
|
503 |
"prompt_number": |
|
|
199 | "prompt_number": 7 | |
|
504 | 200 | }, |
|
505 | 201 | { |
|
506 | 202 | "cell_type": "code", |
|
507 | 203 | "collapsed": false, |
|
508 | 204 | "input": [ |
|
509 | 205 | "G = EventfulGraph()\n", |
|
510 | "echo_graph_events(G)" | |
|
511 |
|
|
|
512 | "language": "python", | |
|
513 | "metadata": {}, | |
|
514 | "outputs": [], | |
|
515 | "prompt_number": 21 | |
|
516 | }, | |
|
517 | { | |
|
518 | "cell_type": "code", | |
|
519 | "collapsed": false, | |
|
520 | "input": [ | |
|
521 | "to_d3_json(G)" | |
|
522 | ], | |
|
523 | "language": "python", | |
|
524 | "metadata": {}, | |
|
525 | "outputs": [ | |
|
526 | { | |
|
527 | "metadata": {}, | |
|
528 | "output_type": "pyout", | |
|
529 | "prompt_number": 22, | |
|
530 | "text": [ | |
|
531 | "'{\"multigraph\": false, \"directed\": false, \"links\": [], \"graph\": [], \"nodes\": []}'" | |
|
532 | ] | |
|
533 | } | |
|
534 | ], | |
|
535 | "prompt_number": 22 | |
|
536 | }, | |
|
537 | { | |
|
538 | "cell_type": "code", | |
|
539 | "collapsed": false, | |
|
540 | "input": [ | |
|
206 | "echo_graph_events(G)\n", | |
|
207 | "\n", | |
|
541 | 208 | "G.add_node('hello')\n", |
|
542 | 209 | "G.add_node('goodbye')\n", |
|
543 |
"G.add_edges_from([(1,2),(1,3)]) |
|
|
544 | "to_d3_json(G)" | |
|
210 | "G.add_edges_from([(1,2),(1,3)])" | |
|
545 | 211 | ], |
|
546 | 212 | "language": "python", |
|
547 | 213 | "metadata": {}, |
@@ -565,17 +231,9 b'' | |||
|
565 | 231 | "adj set (1, {2: {}, 3: {}})\n", |
|
566 | 232 | "adj set (3, {1: {}})\n" |
|
567 | 233 | ] |
|
568 | }, | |
|
569 | { | |
|
570 | "metadata": {}, | |
|
571 | "output_type": "pyout", | |
|
572 | "prompt_number": 23, | |
|
573 | "text": [ | |
|
574 | "'{\"multigraph\": false, \"directed\": false, \"links\": [{\"target\": 1, \"source\": 0}, {\"target\": 3, \"source\": 1}], \"graph\": [], \"nodes\": [{\"id\": 3}, {\"id\": 1}, {\"id\": \"goodbye\"}, {\"id\": 2}, {\"id\": \"hello\"}]}'" | |
|
575 | ] | |
|
576 | 234 | } |
|
577 | 235 | ], |
|
578 |
"prompt_number": |
|
|
236 | "prompt_number": 8 | |
|
579 | 237 | }, |
|
580 | 238 | { |
|
581 | 239 | "cell_type": "code", |
@@ -589,13 +247,13 b'' | |||
|
589 | 247 | { |
|
590 | 248 | "metadata": {}, |
|
591 | 249 | "output_type": "pyout", |
|
592 |
"prompt_number": |
|
|
250 | "prompt_number": 9, | |
|
593 | 251 | "text": [ |
|
594 |
"{3: {1: {}}, 1: {2: {}, 3: {}}, ' |
|
|
252 | "{3: {1: {}}, 1: {2: {}, 3: {}}, 'hello': {}, 2: {1: {}}, 'goodbye': {}}" | |
|
595 | 253 | ] |
|
596 | 254 | } |
|
597 | 255 | ], |
|
598 |
"prompt_number": |
|
|
256 | "prompt_number": 9 | |
|
599 | 257 | }, |
|
600 | 258 | { |
|
601 | 259 | "cell_type": "code", |
@@ -609,58 +267,21 b'' | |||
|
609 | 267 | { |
|
610 | 268 | "metadata": {}, |
|
611 | 269 | "output_type": "pyout", |
|
612 |
"prompt_number": |
|
|
270 | "prompt_number": 10, | |
|
613 | 271 | "text": [ |
|
614 |
"{3: {}, 1: {}, ' |
|
|
272 | "{3: {}, 1: {}, 'hello': {}, 2: {}, 'goodbye': {}}" | |
|
615 | 273 | ] |
|
616 | 274 | } |
|
617 | 275 | ], |
|
618 |
"prompt_number": |
|
|
276 | "prompt_number": 10 | |
|
619 | 277 | }, |
|
620 | 278 | { |
|
621 | 279 | "cell_type": "heading", |
|
622 | 280 | "level": 1, |
|
623 | 281 | "metadata": {}, |
|
624 | 282 | "source": [ |
|
625 |
" |
|
|
626 | ] | |
|
627 | }, | |
|
628 | { | |
|
629 | "cell_type": "code", | |
|
630 | "collapsed": false, | |
|
631 | "input": [ | |
|
632 | "%%html\n", | |
|
633 | "<div id=\"d3loadindicator\" style=\"background: red; color: white;\"><center>Loading D3...<center></div>\n", | |
|
634 | "<script>\n", | |
|
635 | " $.getScript('http://d3js.org/d3.v3.min.js', function(){\n", | |
|
636 | " $('#d3loadindicator')\n", | |
|
637 | " .css('background', 'green')\n", | |
|
638 | " .html('<center>D3 Loaded Successfully</center>');\n", | |
|
639 | " });\n", | |
|
640 | "</script>" | |
|
641 | ], | |
|
642 | "language": "python", | |
|
643 | "metadata": {}, | |
|
644 | "outputs": [ | |
|
645 | { | |
|
646 | "html": [ | |
|
647 | "<div id=\"d3loadindicator\" style=\"background: red; color: white;\"><center>Loading D3...<center></div>\n", | |
|
648 | "<script>\n", | |
|
649 | " $.getScript('http://d3js.org/d3.v3.min.js', function(){\n", | |
|
650 | " $('#d3loadindicator')\n", | |
|
651 | " .css('background', 'green')\n", | |
|
652 | " .html('<center>D3 Loaded Successfully</center>');\n", | |
|
653 | " });\n", | |
|
654 | "</script>" | |
|
655 | ], | |
|
656 | "metadata": {}, | |
|
657 | "output_type": "display_data", | |
|
658 | "text": [ | |
|
659 | "<IPython.core.display.HTML at 0x7fa801877d90>" | |
|
283 | "D3 Widget" | |
|
660 | 284 |
|
|
661 | } | |
|
662 | ], | |
|
663 | "prompt_number": 26 | |
|
664 | 285 | }, |
|
665 | 286 | { |
|
666 | 287 | "cell_type": "code", |
@@ -672,7 +293,7 b'' | |||
|
672 | 293 | "language": "python", |
|
673 | 294 | "metadata": {}, |
|
674 | 295 | "outputs": [], |
|
675 |
"prompt_number": |
|
|
296 | "prompt_number": 11 | |
|
676 | 297 | }, |
|
677 | 298 | { |
|
678 | 299 | "cell_type": "code", |
@@ -687,9 +308,6 b'' | |||
|
687 | 308 | " target_name = Unicode('ForceDirectedGraphModel')\n", |
|
688 | 309 | " default_view_name = Unicode('D3ForceDirectedGraphView')\n", |
|
689 | 310 | " \n", |
|
690 | " _keys = ['initial_json']\n", | |
|
691 | " initial_json = Unicode()\n", | |
|
692 | " \n", | |
|
693 | 311 | " def __init__(self, eventful_graph, *pargs, **kwargs):\n", |
|
694 | 312 | " Widget.__init__(self, *pargs, **kwargs)\n", |
|
695 | 313 | " \n", |
@@ -700,8 +318,15 b'' | |||
|
700 | 318 | " \n", |
|
701 | 319 | " \n", |
|
702 | 320 | " def _repr_widget_(self, *pargs, **kwargs):\n", |
|
703 | " self.initial_json = to_d3_json(self._eventful_graph)\n", | |
|
321 | " \n", | |
|
322 | " # Show the widget, then send the current state\n", | |
|
704 | 323 | " Widget._repr_widget_(self, *pargs, **kwargs)\n", |
|
324 | " for (key, value) in self._eventful_graph.graph.items():\n", | |
|
325 | " self.send({'dict': 'graph', 'action': 'add', 'key': key, 'value': value})\n", | |
|
326 | " for (key, value) in self._eventful_graph.node.items():\n", | |
|
327 | " self.send({'dict': 'node', 'action': 'add', 'key': key, 'value': value})\n", | |
|
328 | " for (key, value) in self._eventful_graph.adj.items():\n", | |
|
329 | " self.send({'dict': 'adj', 'action': 'add', 'key': key, 'value': value})\n", | |
|
705 | 330 | " \n", |
|
706 | 331 | " \n", |
|
707 | 332 | " def _send_dict_changes(self, eventful_dict, dict_name):\n", |
@@ -719,7 +344,7 b'' | |||
|
719 | 344 | "language": "python", |
|
720 | 345 | "metadata": {}, |
|
721 | 346 | "outputs": [], |
|
722 |
"prompt_number": 2 |
|
|
347 | "prompt_number": 20 | |
|
723 | 348 | }, |
|
724 | 349 | { |
|
725 | 350 | "cell_type": "code", |
@@ -727,7 +352,7 b'' | |||
|
727 | 352 | "input": [ |
|
728 | 353 | "%%javascript\n", |
|
729 | 354 | "\n", |
|
730 | "require([\"notebook/js/widget\"], function(){\n", | |
|
355 | "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n", | |
|
731 | 356 | " \n", |
|
732 | 357 | " // Define the ForceDirectedGraphModel and register it with the widget manager.\n", |
|
733 | 358 | " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n", |
@@ -740,6 +365,7 b'' | |||
|
740 | 365 | " this.guid = 'd3force' + IPython.utils.uuid();\n", |
|
741 | 366 | " this.setElement($('<div />', {id: this.guid}));\n", |
|
742 | 367 | " this.model.on_msg($.proxy(this.handle_msg, this));\n", |
|
368 | " this.has_drawn = false;\n", | |
|
743 | 369 | " },\n", |
|
744 | 370 | " \n", |
|
745 | 371 | " add_node: function(id){\n", |
@@ -860,34 +486,28 b'' | |||
|
860 | 486 | " },\n", |
|
861 | 487 | " \n", |
|
862 | 488 | " update: function(){\n", |
|
863 | " var initial_json = this.model.get('initial_json');\n", | |
|
864 |
" |
|
|
865 | " this.initial_json = initial_json;\n", | |
|
489 | " if (! this.has_drawn) {\n", | |
|
490 | " this.has_drawn = true;\n", | |
|
866 | 491 | " \n", |
|
867 |
" var width = |
|
|
868 |
" height = |
|
|
492 | " var width = 400,\n", | |
|
493 | " height = 300;\n", | |
|
869 | 494 | " \n", |
|
870 | 495 | " this.color = d3.scale.category20();\n", |
|
871 | 496 | " \n", |
|
872 | " var graph = JSON.parse(initial_json);\n", | |
|
873 | 497 | " this.nodes = [];\n", |
|
874 | " $.extend(this.nodes, graph.nodes);\n", | |
|
875 | 498 | " this.links = [];\n", |
|
876 | " $.extend(this.links, graph.links);\n", | |
|
877 | 499 | " \n", |
|
878 |
" |
|
|
500 | " this.force = d3.layout.force()\n", | |
|
879 | 501 | " .nodes(this.nodes)\n", |
|
880 | 502 | " .links(this.links)\n", |
|
881 | 503 | " .charge(-120)\n", |
|
882 | 504 | " .linkDistance(30)\n", |
|
883 | 505 | " .size([width, height])\n", |
|
884 | 506 | " .on(\"tick\", $.proxy(this.tick, this));\n", |
|
885 | " this.force = force;\n", | |
|
886 | 507 | " \n", |
|
887 |
" |
|
|
508 | " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n", | |
|
888 | 509 | " .attr(\"width\", width)\n", |
|
889 | 510 | " .attr(\"height\", height);\n", |
|
890 | " this.svg = svg;\n", | |
|
891 | 511 | " \n", |
|
892 | 512 | " var that = this;\n", |
|
893 | 513 | " setTimeout(function() {\n", |
@@ -910,7 +530,7 b'' | |||
|
910 | 530 | { |
|
911 | 531 | "javascript": [ |
|
912 | 532 | "\n", |
|
913 | "require([\"notebook/js/widget\"], function(){\n", | |
|
533 | "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n", | |
|
914 | 534 | " \n", |
|
915 | 535 | " // Define the ForceDirectedGraphModel and register it with the widget manager.\n", |
|
916 | 536 | " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n", |
@@ -923,6 +543,7 b'' | |||
|
923 | 543 | " this.guid = 'd3force' + IPython.utils.uuid();\n", |
|
924 | 544 | " this.setElement($('<div />', {id: this.guid}));\n", |
|
925 | 545 | " this.model.on_msg($.proxy(this.handle_msg, this));\n", |
|
546 | " this.has_drawn = false;\n", | |
|
926 | 547 | " },\n", |
|
927 | 548 | " \n", |
|
928 | 549 | " add_node: function(id){\n", |
@@ -1043,34 +664,28 b'' | |||
|
1043 | 664 | " },\n", |
|
1044 | 665 | " \n", |
|
1045 | 666 | " update: function(){\n", |
|
1046 | " var initial_json = this.model.get('initial_json');\n", | |
|
1047 |
" |
|
|
1048 | " this.initial_json = initial_json;\n", | |
|
667 | " if (! this.has_drawn) {\n", | |
|
668 | " this.has_drawn = true;\n", | |
|
1049 | 669 | " \n", |
|
1050 |
" var width = |
|
|
1051 |
" height = |
|
|
670 | " var width = 400,\n", | |
|
671 | " height = 300;\n", | |
|
1052 | 672 | " \n", |
|
1053 | 673 | " this.color = d3.scale.category20();\n", |
|
1054 | 674 | " \n", |
|
1055 | " var graph = JSON.parse(initial_json);\n", | |
|
1056 | 675 | " this.nodes = [];\n", |
|
1057 | " $.extend(this.nodes, graph.nodes);\n", | |
|
1058 | 676 | " this.links = [];\n", |
|
1059 | " $.extend(this.links, graph.links);\n", | |
|
1060 | 677 | " \n", |
|
1061 |
" |
|
|
678 | " this.force = d3.layout.force()\n", | |
|
1062 | 679 | " .nodes(this.nodes)\n", |
|
1063 | 680 | " .links(this.links)\n", |
|
1064 | 681 | " .charge(-120)\n", |
|
1065 | 682 | " .linkDistance(30)\n", |
|
1066 | 683 | " .size([width, height])\n", |
|
1067 | 684 | " .on(\"tick\", $.proxy(this.tick, this));\n", |
|
1068 | " this.force = force;\n", | |
|
1069 | 685 | " \n", |
|
1070 |
" |
|
|
686 | " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n", | |
|
1071 | 687 | " .attr(\"width\", width)\n", |
|
1072 | 688 | " .attr(\"height\", height);\n", |
|
1073 | " this.svg = svg;\n", | |
|
1074 | 689 | " \n", |
|
1075 | 690 | " var that = this;\n", |
|
1076 | 691 | " setTimeout(function() {\n", |
@@ -1090,11 +705,19 b'' | |||
|
1090 | 705 | "metadata": {}, |
|
1091 | 706 | "output_type": "display_data", |
|
1092 | 707 | "text": [ |
|
1093 |
"<IPython.core.display.Javascript at 0x7f |
|
|
708 | "<IPython.core.display.Javascript at 0x7fdee9b02590>" | |
|
1094 | 709 | ] |
|
1095 | 710 | } |
|
1096 | 711 | ], |
|
1097 |
"prompt_number": 2 |
|
|
712 | "prompt_number": 28 | |
|
713 | }, | |
|
714 | { | |
|
715 | "cell_type": "heading", | |
|
716 | "level": 1, | |
|
717 | "metadata": {}, | |
|
718 | "source": [ | |
|
719 | "Test" | |
|
720 | ] | |
|
1098 | 721 | }, |
|
1099 | 722 | { |
|
1100 | 723 | "cell_type": "code", |
@@ -1103,55 +726,25 b'' | |||
|
1103 | 726 | "G = EventfulGraph()\n", |
|
1104 | 727 | "G.add_node('hello')\n", |
|
1105 | 728 | "G.add_node('goodbye')\n", |
|
1106 |
"G.add_edges_from([(1,2),(1,3)]) |
|
|
1107 | "to_d3_json(G)" | |
|
729 | "G.add_edges_from([(1,2),(1,3)])" | |
|
1108 | 730 | ], |
|
1109 | 731 | "language": "python", |
|
1110 | 732 | "metadata": {}, |
|
1111 | "outputs": [ | |
|
1112 | { | |
|
1113 | "metadata": {}, | |
|
1114 | "output_type": "pyout", | |
|
1115 | "prompt_number": 36, | |
|
1116 | "text": [ | |
|
1117 | "'{\"multigraph\": false, \"directed\": false, \"links\": [{\"target\": 1, \"source\": 0}, {\"target\": 3, \"source\": 1}], \"graph\": [], \"nodes\": [{\"id\": 3}, {\"id\": 1}, {\"id\": \"goodbye\"}, {\"id\": 2}, {\"id\": \"hello\"}]}'" | |
|
1118 | ] | |
|
1119 | } | |
|
1120 | ], | |
|
1121 | "prompt_number": 36 | |
|
733 | "outputs": [], | |
|
734 | "prompt_number": 29 | |
|
1122 | 735 | }, |
|
1123 | 736 | { |
|
1124 | 737 | "cell_type": "code", |
|
1125 | 738 | "collapsed": false, |
|
1126 | 739 | "input": [ |
|
1127 | "floating_container = widgets.ContainerWidget()\n", | |
|
1128 | "floating_container.set_css({\n", | |
|
1129 | " 'position': 'relative',\n", | |
|
1130 | " 'left': '0px',\n", | |
|
1131 | " 'top': '0px',\n", | |
|
1132 | " 'z-index': '999',\n", | |
|
1133 | " 'background': '#FFF',\n", | |
|
1134 | " 'opacity': '0.8'\n", | |
|
1135 | "})\n", | |
|
740 | "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n", | |
|
1136 | 741 | "\n", |
|
1137 | 742 | "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n", |
|
1138 |
"display(floating_container) |
|
|
1139 | "\n", | |
|
1140 | "detach_button = widgets.ButtonWidget(description=\"Detach\")\n", | |
|
1141 | "def handle_detach(sender):\n", | |
|
1142 | " if sender.description == \"Detach\":\n", | |
|
1143 | " sender.description = \"Attach\"\n", | |
|
1144 | " floating_container.set_css('position', 'absolute')\n", | |
|
1145 | " else:\n", | |
|
1146 | " sender.description = \"Detach\"\n", | |
|
1147 | " floating_container.set_css('position', 'relative')\n", | |
|
1148 | "detach_button.on_click(handle_detach)\n", | |
|
1149 | "display(detach_button)" | |
|
743 | "display(floating_container)" | |
|
1150 | 744 | ], |
|
1151 | 745 | "language": "python", |
|
1152 | 746 | "metadata": {}, |
|
1153 |
"outputs": [] |
|
|
1154 | "prompt_number": 37 | |
|
747 | "outputs": [] | |
|
1155 | 748 | }, |
|
1156 | 749 | { |
|
1157 | 750 | "cell_type": "code", |
@@ -1163,7 +756,7 b'' | |||
|
1163 | 756 | "language": "python", |
|
1164 | 757 | "metadata": {}, |
|
1165 | 758 | "outputs": [], |
|
1166 |
"prompt_number": |
|
|
759 | "prompt_number": 25 | |
|
1167 | 760 | }, |
|
1168 | 761 | { |
|
1169 | 762 | "cell_type": "code", |
@@ -1174,7 +767,7 b'' | |||
|
1174 | 767 | "language": "python", |
|
1175 | 768 | "metadata": {}, |
|
1176 | 769 | "outputs": [], |
|
1177 |
"prompt_number": |
|
|
770 | "prompt_number": 26 | |
|
1178 | 771 | }, |
|
1179 | 772 | { |
|
1180 | 773 | "cell_type": "code", |
@@ -1186,7 +779,7 b'' | |||
|
1186 | 779 | "language": "python", |
|
1187 | 780 | "metadata": {}, |
|
1188 | 781 | "outputs": [], |
|
1189 |
"prompt_number": |
|
|
782 | "prompt_number": 27 | |
|
1190 | 783 | }, |
|
1191 | 784 | { |
|
1192 | 785 | "cell_type": "code", |
General Comments 0
You need to be logged in to leave comments.
Login now