##// END OF EJS Templates
Added tweet watch example
Jonathan Frederic -
Show More
This diff has been collapsed as it changes many lines, (568 lines changed) Show them Hide them
@@ -18,7 +18,7 b''
18 "language": "python",
18 "language": "python",
19 "metadata": {},
19 "metadata": {},
20 "outputs": [],
20 "outputs": [],
21 "prompt_number": 13
21 "prompt_number": 1
22 },
22 },
23 {
23 {
24 "cell_type": "markdown",
24 "cell_type": "markdown",
@@ -138,7 +138,7 b''
138 "language": "python",
138 "language": "python",
139 "metadata": {},
139 "metadata": {},
140 "outputs": [],
140 "outputs": [],
141 "prompt_number": 14
141 "prompt_number": 2
142 },
142 },
143 {
143 {
144 "cell_type": "markdown",
144 "cell_type": "markdown",
@@ -165,7 +165,7 b''
165 "language": "python",
165 "language": "python",
166 "metadata": {},
166 "metadata": {},
167 "outputs": [],
167 "outputs": [],
168 "prompt_number": 15
168 "prompt_number": 3
169 },
169 },
170 {
170 {
171 "cell_type": "markdown",
171 "cell_type": "markdown",
@@ -196,7 +196,7 b''
196 "language": "python",
196 "language": "python",
197 "metadata": {},
197 "metadata": {},
198 "outputs": [],
198 "outputs": [],
199 "prompt_number": 16
199 "prompt_number": 4
200 },
200 },
201 {
201 {
202 "cell_type": "code",
202 "cell_type": "code",
@@ -206,8 +206,8 b''
206 "echo_graph_events(G)\n",
206 "echo_graph_events(G)\n",
207 "\n",
207 "\n",
208 "G.add_node('hello')\n",
208 "G.add_node('hello')\n",
209 "G.add_node('goodbye', color=\"red\")\n",
209 "G.add_node('goodbye', fill=\"red\")\n",
210 "G.add_edges_from([(1,2),(1,3), (1,'goodbye')])"
210 "G.add_edges_from([(1,2),(1,3), (1,'goodbye')], stroke=\"lime\")"
211 ],
211 ],
212 "language": "python",
212 "language": "python",
213 "metadata": {},
213 "metadata": {},
@@ -219,23 +219,23 b''
219 "adj add (hello, {})\n",
219 "adj add (hello, {})\n",
220 "node add (hello, {})\n",
220 "node add (hello, {})\n",
221 "adj add (goodbye, {})\n",
221 "adj add (goodbye, {})\n",
222 "node add (goodbye, {'color': 'red'})\n",
222 "node add (goodbye, {'fill': 'red'})\n",
223 "adj add (1, {})\n",
223 "adj add (1, {})\n",
224 "node add (1, {})\n",
224 "node add (1, {})\n",
225 "adj add (2, {})\n",
225 "adj add (2, {})\n",
226 "node add (2, {})\n",
226 "node add (2, {})\n",
227 "adj set (1, {2: {}})\n",
227 "adj set (1, {2: {'stroke': 'lime'}})\n",
228 "adj set (2, {1: {}})\n",
228 "adj set (2, {1: {'stroke': 'lime'}})\n",
229 "adj add (3, {})\n",
229 "adj add (3, {})\n",
230 "node add (3, {})\n",
230 "node add (3, {})\n",
231 "adj set (1, {2: {}, 3: {}})\n",
231 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}})\n",
232 "adj set (3, {1: {}})\n",
232 "adj set (3, {1: {'stroke': 'lime'}})\n",
233 "adj set (1, {2: {}, 3: {}, 'goodbye': {}})\n",
233 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
234 "adj set (goodbye, {1: {}})\n"
234 "adj set (goodbye, {1: {'stroke': 'lime'}})\n"
235 ]
235 ]
236 }
236 }
237 ],
237 ],
238 "prompt_number": 43
238 "prompt_number": 5
239 },
239 },
240 {
240 {
241 "cell_type": "code",
241 "cell_type": "code",
@@ -249,13 +249,19 b''
249 {
249 {
250 "metadata": {},
250 "metadata": {},
251 "output_type": "pyout",
251 "output_type": "pyout",
252 "prompt_number": 18,
252 "prompt_number": 6,
253 "text": [
253 "text": [
254 "{3: {1: {}}, 1: {2: {}, 3: {}}, 'goodbye': {}, 2: {1: {}}, 'hello': {}}"
254 "{'hello': {},\n",
255 " 2: {1: {'stroke': 'lime'}},\n",
256 " 3: {1: {'stroke': 'lime'}},\n",
257 " 'goodbye': {1: {'stroke': 'lime'}},\n",
258 " 1: {2: {'stroke': 'lime'},\n",
259 " 3: {'stroke': 'lime'},\n",
260 " 'goodbye': {'stroke': 'lime'}}}"
255 ]
261 ]
256 }
262 }
257 ],
263 ],
258 "prompt_number": 18
264 "prompt_number": 6
259 },
265 },
260 {
266 {
261 "cell_type": "code",
267 "cell_type": "code",
@@ -269,13 +275,13 b''
269 {
275 {
270 "metadata": {},
276 "metadata": {},
271 "output_type": "pyout",
277 "output_type": "pyout",
272 "prompt_number": 19,
278 "prompt_number": 7,
273 "text": [
279 "text": [
274 "{3: {}, 1: {}, 'goodbye': {}, 2: {}, 'hello': {}}"
280 "{'hello': {}, 2: {}, 3: {}, 'goodbye': {'fill': 'red'}, 1: {}}"
275 ]
281 ]
276 }
282 }
277 ],
283 ],
278 "prompt_number": 19
284 "prompt_number": 7
279 },
285 },
280 {
286 {
281 "cell_type": "heading",
287 "cell_type": "heading",
@@ -286,6 +292,13 b''
286 ]
292 ]
287 },
293 },
288 {
294 {
295 "cell_type": "markdown",
296 "metadata": {},
297 "source": [
298 "The D3 widget will blindly port all of the dictionary events over custom widget messages."
299 ]
300 },
301 {
289 "cell_type": "code",
302 "cell_type": "code",
290 "collapsed": false,
303 "collapsed": false,
291 "input": [
304 "input": [
@@ -295,7 +308,7 b''
295 "language": "python",
308 "language": "python",
296 "metadata": {},
309 "metadata": {},
297 "outputs": [],
310 "outputs": [],
298 "prompt_number": 20
311 "prompt_number": 8
299 },
312 },
300 {
313 {
301 "cell_type": "code",
314 "cell_type": "code",
@@ -350,7 +363,14 b''
350 "language": "python",
363 "language": "python",
351 "metadata": {},
364 "metadata": {},
352 "outputs": [],
365 "outputs": [],
353 "prompt_number": 31
366 "prompt_number": 9
367 },
368 {
369 "cell_type": "markdown",
370 "metadata": {},
371 "source": [
372 "The front-end listens to the dictionary events and keeps the D3 control in sync with the dictionary in the back-end."
373 ]
354 },
374 },
355 {
375 {
356 "cell_type": "code",
376 "cell_type": "code",
@@ -374,7 +394,7 b''
374 " this.has_drawn = false;\n",
394 " this.has_drawn = false;\n",
375 " },\n",
395 " },\n",
376 " \n",
396 " \n",
377 " add_node: function(id){\n",
397 " try_add_node: function(id){\n",
378 " var index = this.find_node(id);\n",
398 " var index = this.find_node(id);\n",
379 " if (index == -1) {\n",
399 " if (index == -1) {\n",
380 " var node = {id: id};\n",
400 " var node = {id: id};\n",
@@ -385,23 +405,22 b''
385 " }\n",
405 " }\n",
386 " },\n",
406 " },\n",
387 " \n",
407 " \n",
388 " set_node: function(id, attributes) {\n",
408 " update_node: function(node, attributes) {\n",
389 " var index = this.find_node(id);\n",
409 " if (node !== null) {\n",
390 " if (index != -1) {\n",
391 " for (var key in attributes) {\n",
410 " for (var key in attributes) {\n",
392 " this.nodes[index][key] = attributes[key];\n",
411 " node[key] = attributes[key];\n",
393 " }\n",
412 " }\n",
394 " this._update_node(d3.select('#'+this.guid+id));\n",
413 " this._update_node(d3.select('#' + this.guid + node.id));\n",
395 " }\n",
414 " }\n",
396 " },\n",
415 " },\n",
397 " \n",
416 " \n",
398 " remove_node: function(id){\n",
417 " remove_node: function(id){\n",
418 " this.remove_links_to(id);\n",
419 " \n",
399 " var found_index = this.find_node(id);\n",
420 " var found_index = this.find_node(id);\n",
400 " if (found_index>=0) {\n",
421 " if (found_index>=0) {\n",
401 " this.nodes.splice(found_index, 1);\n",
422 " this.nodes.splice(found_index, 1);\n",
402 " }\n",
423 " }\n",
403 " \n",
404 " clear_links(id);\n",
405 " },\n",
424 " },\n",
406 " \n",
425 " \n",
407 " find_node: function(id){\n",
426 " find_node: function(id){\n",
@@ -415,19 +434,63 b''
415 " return found_index;\n",
434 " return found_index;\n",
416 " },\n",
435 " },\n",
417 " \n",
436 " \n",
418 " clear_links: function(id){\n",
437 " find_link: function(source_id, target_id){\n",
419 " \n",
420 " // Remove existing links\n",
421 " var found_indexs = [];\n",
422 " for (var index in this.links) {\n",
438 " for (var index in this.links) {\n",
423 " if (this.links[index].source.id == id) {\n",
439 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
424 " found_indexs.push(index);\n",
440 " return index;\n",
425 " }\n",
441 " }\n",
426 " }\n",
442 " }\n",
443 " return -1;\n",
444 " },\n",
445 " \n",
446 " try_add_link: function(source_id, target_id){\n",
447 " var index = this.find_link(source_id, target_id);\n",
448 " if (index == -1) {\n",
449 " var source_node = this.try_add_node(source_id);\n",
450 " var target_node = this.try_add_node(target_id);\n",
451 " var new_link = {source: source_node, target: target_node};\n",
452 " this.links.push(new_link);\n",
453 " return new_link;\n",
454 " } else {\n",
455 " return this.links[index]\n",
456 " }\n",
457 " },\n",
458 " \n",
459 " update_link: function(link, attributes){\n",
460 " if (link != null) {\n",
461 " for (var key in attributes) {\n",
462 " link[key] = attributes[key];\n",
463 " }\n",
464 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
465 " }\n",
466 " },\n",
467 " \n",
468 " remove_links: function(source_id){\n",
469 " var found_indicies = [];\n",
470 " for (var index in this.links) {\n",
471 " if (this.links[index].source.id == source_id) {\n",
472 " found_indicies.push(index);\n",
473 " }\n",
474 " }\n",
475 " found_indicies.reverse();\n",
427 " \n",
476 " \n",
428 " for (var index in found_indexs) {\n",
477 " for (var index in found_indicies) {\n",
429 " this.links.splice(found_indexs[index], 1);\n",
478 " this.links.splice(index, 1);\n",
479 " };\n",
480 " },\n",
481 " \n",
482 " remove_links_to: function(id){\n",
483 " var found_indicies = [];\n",
484 " for (var index in this.links) {\n",
485 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
486 " found_indicies.push(index);\n",
487 " }\n",
430 " }\n",
488 " }\n",
489 " found_indicies.reverse();\n",
490 " \n",
491 " for (var index in found_indicies) {\n",
492 " this.links.splice(index, 1);\n",
493 " };\n",
431 " },\n",
494 " },\n",
432 " \n",
495 " \n",
433 " handle_msg: function(content){\n",
496 " handle_msg: function(content){\n",
@@ -437,24 +500,19 b''
437 " \n",
500 " \n",
438 " if (dict=='node') {\n",
501 " if (dict=='node') {\n",
439 " if (action=='add' || action=='set') {\n",
502 " if (action=='add' || action=='set') {\n",
440 " var value = content.value;\n",
503 " this.update_node(this.try_add_node(key), content.value)\n",
441 " this.add_node(key)\n",
442 " this.set_node(key, value)\n",
443 " } else if (action=='del') {\n",
504 " } else if (action=='del') {\n",
444 " this.remove_node(key);\n",
505 " this.remove_node(key);\n",
445 " }\n",
506 " }\n",
446 " \n",
507 " \n",
447 " } else if (dict=='adj') {\n",
508 " } else if (dict=='adj') {\n",
448 " this.clear_links(key);\n",
509 " if (action=='add' || action=='set') {\n",
449 " \n",
510 " var links = content.value;\n",
450 " // Add all links\n",
511 " for (var target_id in links) {\n",
451 " if (action != 'del') {\n",
512 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
452 " var value = content.value;\n",
453 " for (var link_to in value) {\n",
454 " var source_node = this.add_node(key);\n",
455 " var target_node = this.add_node(link_to);\n",
456 " this.links.push({source: source_node, target: target_node});\n",
457 " }\n",
513 " }\n",
514 " } else if (action=='del') {\n",
515 " this.remove_links(key);\n",
458 " }\n",
516 " }\n",
459 " }\n",
517 " }\n",
460 " this.start();\n",
518 " this.start();\n",
@@ -517,6 +575,7 b''
517 " },\n",
575 " },\n",
518 " \n",
576 " \n",
519 " _update_edge: function(edge) {\n",
577 " _update_edge: function(edge) {\n",
578 " var that = this;\n",
520 " edge\n",
579 " edge\n",
521 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
580 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
522 " .attr(\"class\", \"link\")\n",
581 " .attr(\"class\", \"link\")\n",
@@ -566,8 +625,27 b''
566 " this.force = d3.layout.force()\n",
625 " this.force = d3.layout.force()\n",
567 " .nodes(this.nodes)\n",
626 " .nodes(this.nodes)\n",
568 " .links(this.links)\n",
627 " .links(this.links)\n",
569 " .charge(-120)\n",
628 " .charge(function (d) {\n",
570 " .linkDistance(30)\n",
629 " if (d.charge === undefined) {\n",
630 " return -120;\n",
631 " } else {\n",
632 " return d.charge;\n",
633 " }\n",
634 " })\n",
635 " .linkDistance(function (d) {\n",
636 " if (d.distance === undefined) {\n",
637 " return 40;\n",
638 " } else {\n",
639 " return d.distance;\n",
640 " }\n",
641 " })\n",
642 " .linkStrength(function (d) {\n",
643 " if (d.strength === undefined) {\n",
644 " return 1.0;\n",
645 " } else {\n",
646 " return d.strength;\n",
647 " }\n",
648 " })\n",
571 " .size([width, height])\n",
649 " .size([width, height])\n",
572 " .on(\"tick\", $.proxy(this.tick, this));\n",
650 " .on(\"tick\", $.proxy(this.tick, this));\n",
573 " \n",
651 " \n",
@@ -612,7 +690,7 b''
612 " this.has_drawn = false;\n",
690 " this.has_drawn = false;\n",
613 " },\n",
691 " },\n",
614 " \n",
692 " \n",
615 " add_node: function(id){\n",
693 " try_add_node: function(id){\n",
616 " var index = this.find_node(id);\n",
694 " var index = this.find_node(id);\n",
617 " if (index == -1) {\n",
695 " if (index == -1) {\n",
618 " var node = {id: id};\n",
696 " var node = {id: id};\n",
@@ -623,23 +701,22 b''
623 " }\n",
701 " }\n",
624 " },\n",
702 " },\n",
625 " \n",
703 " \n",
626 " set_node: function(id, attributes) {\n",
704 " update_node: function(node, attributes) {\n",
627 " var index = this.find_node(id);\n",
705 " if (node !== null) {\n",
628 " if (index != -1) {\n",
629 " for (var key in attributes) {\n",
706 " for (var key in attributes) {\n",
630 " this.nodes[index][key] = attributes[key];\n",
707 " node[key] = attributes[key];\n",
631 " }\n",
708 " }\n",
632 " this._update_node(d3.select('#'+this.guid+id));\n",
709 " this._update_node(d3.select('#' + this.guid + node.id));\n",
633 " }\n",
710 " }\n",
634 " },\n",
711 " },\n",
635 " \n",
712 " \n",
636 " remove_node: function(id){\n",
713 " remove_node: function(id){\n",
714 " this.remove_links_to(id);\n",
715 " \n",
637 " var found_index = this.find_node(id);\n",
716 " var found_index = this.find_node(id);\n",
638 " if (found_index>=0) {\n",
717 " if (found_index>=0) {\n",
639 " this.nodes.splice(found_index, 1);\n",
718 " this.nodes.splice(found_index, 1);\n",
640 " }\n",
719 " }\n",
641 " \n",
642 " clear_links(id);\n",
643 " },\n",
720 " },\n",
644 " \n",
721 " \n",
645 " find_node: function(id){\n",
722 " find_node: function(id){\n",
@@ -653,19 +730,63 b''
653 " return found_index;\n",
730 " return found_index;\n",
654 " },\n",
731 " },\n",
655 " \n",
732 " \n",
656 " clear_links: function(id){\n",
733 " find_link: function(source_id, target_id){\n",
657 " \n",
734 " for (var index in this.links) {\n",
658 " // Remove existing links\n",
735 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
659 " var found_indexs = [];\n",
736 " return index;\n",
737 " }\n",
738 " }\n",
739 " return -1;\n",
740 " },\n",
741 " \n",
742 " try_add_link: function(source_id, target_id){\n",
743 " var index = this.find_link(source_id, target_id);\n",
744 " if (index == -1) {\n",
745 " var source_node = this.try_add_node(source_id);\n",
746 " var target_node = this.try_add_node(target_id);\n",
747 " var new_link = {source: source_node, target: target_node};\n",
748 " this.links.push(new_link);\n",
749 " return new_link;\n",
750 " } else {\n",
751 " return this.links[index]\n",
752 " }\n",
753 " },\n",
754 " \n",
755 " update_link: function(link, attributes){\n",
756 " if (link != null) {\n",
757 " for (var key in attributes) {\n",
758 " link[key] = attributes[key];\n",
759 " }\n",
760 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
761 " }\n",
762 " },\n",
763 " \n",
764 " remove_links: function(source_id){\n",
765 " var found_indicies = [];\n",
660 " for (var index in this.links) {\n",
766 " for (var index in this.links) {\n",
661 " if (this.links[index].source.id == id) {\n",
767 " if (this.links[index].source.id == source_id) {\n",
662 " found_indexs.push(index);\n",
768 " found_indicies.push(index);\n",
663 " }\n",
769 " }\n",
664 " }\n",
770 " }\n",
771 " found_indicies.reverse();\n",
665 " \n",
772 " \n",
666 " for (var index in found_indexs) {\n",
773 " for (var index in found_indicies) {\n",
667 " this.links.splice(found_indexs[index], 1);\n",
774 " this.links.splice(index, 1);\n",
775 " };\n",
776 " },\n",
777 " \n",
778 " remove_links_to: function(id){\n",
779 " var found_indicies = [];\n",
780 " for (var index in this.links) {\n",
781 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
782 " found_indicies.push(index);\n",
783 " }\n",
668 " }\n",
784 " }\n",
785 " found_indicies.reverse();\n",
786 " \n",
787 " for (var index in found_indicies) {\n",
788 " this.links.splice(index, 1);\n",
789 " };\n",
669 " },\n",
790 " },\n",
670 " \n",
791 " \n",
671 " handle_msg: function(content){\n",
792 " handle_msg: function(content){\n",
@@ -675,24 +796,19 b''
675 " \n",
796 " \n",
676 " if (dict=='node') {\n",
797 " if (dict=='node') {\n",
677 " if (action=='add' || action=='set') {\n",
798 " if (action=='add' || action=='set') {\n",
678 " var value = content.value;\n",
799 " this.update_node(this.try_add_node(key), content.value)\n",
679 " this.add_node(key)\n",
680 " this.set_node(key, value)\n",
681 " } else if (action=='del') {\n",
800 " } else if (action=='del') {\n",
682 " this.remove_node(key);\n",
801 " this.remove_node(key);\n",
683 " }\n",
802 " }\n",
684 " \n",
803 " \n",
685 " } else if (dict=='adj') {\n",
804 " } else if (dict=='adj') {\n",
686 " this.clear_links(key);\n",
805 " if (action=='add' || action=='set') {\n",
687 " \n",
806 " var links = content.value;\n",
688 " // Add all links\n",
807 " for (var target_id in links) {\n",
689 " if (action != 'del') {\n",
808 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
690 " var value = content.value;\n",
691 " for (var link_to in value) {\n",
692 " var source_node = this.add_node(key);\n",
693 " var target_node = this.add_node(link_to);\n",
694 " this.links.push({source: source_node, target: target_node});\n",
695 " }\n",
809 " }\n",
810 " } else if (action=='del') {\n",
811 " this.remove_links(key);\n",
696 " }\n",
812 " }\n",
697 " }\n",
813 " }\n",
698 " this.start();\n",
814 " this.start();\n",
@@ -755,7 +871,9 b''
755 " },\n",
871 " },\n",
756 " \n",
872 " \n",
757 " _update_edge: function(edge) {\n",
873 " _update_edge: function(edge) {\n",
874 " var that = this;\n",
758 " edge\n",
875 " edge\n",
876 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
759 " .attr(\"class\", \"link\")\n",
877 " .attr(\"class\", \"link\")\n",
760 " .style(\"stroke-width\", function(d) {\n",
878 " .style(\"stroke-width\", function(d) {\n",
761 " if (d.strokewidth == undefined) {\n",
879 " if (d.strokewidth == undefined) {\n",
@@ -803,8 +921,27 b''
803 " this.force = d3.layout.force()\n",
921 " this.force = d3.layout.force()\n",
804 " .nodes(this.nodes)\n",
922 " .nodes(this.nodes)\n",
805 " .links(this.links)\n",
923 " .links(this.links)\n",
806 " .charge(-120)\n",
924 " .charge(function (d) {\n",
807 " .linkDistance(30)\n",
925 " if (d.charge === undefined) {\n",
926 " return -120;\n",
927 " } else {\n",
928 " return d.charge;\n",
929 " }\n",
930 " })\n",
931 " .linkDistance(function (d) {\n",
932 " if (d.distance === undefined) {\n",
933 " return 40;\n",
934 " } else {\n",
935 " return d.distance;\n",
936 " }\n",
937 " })\n",
938 " .linkStrength(function (d) {\n",
939 " if (d.strength === undefined) {\n",
940 " return 1.0;\n",
941 " } else {\n",
942 " return d.strength;\n",
943 " }\n",
944 " })\n",
808 " .size([width, height])\n",
945 " .size([width, height])\n",
809 " .on(\"tick\", $.proxy(this.tick, this));\n",
946 " .on(\"tick\", $.proxy(this.tick, this));\n",
810 " \n",
947 " \n",
@@ -830,11 +967,11 b''
830 "metadata": {},
967 "metadata": {},
831 "output_type": "display_data",
968 "output_type": "display_data",
832 "text": [
969 "text": [
833 "<IPython.core.display.Javascript at 0x7fde93573a90>"
970 "<IPython.core.display.Javascript at 0x7fc26c030890>"
834 ]
971 ]
835 }
972 }
836 ],
973 ],
837 "prompt_number": 138
974 "prompt_number": 10
838 },
975 },
839 {
976 {
840 "cell_type": "heading",
977 "cell_type": "heading",
@@ -848,20 +985,6 b''
848 "cell_type": "code",
985 "cell_type": "code",
849 "collapsed": false,
986 "collapsed": false,
850 "input": [
987 "input": [
851 "G = EventfulGraph()\n",
852 "G.add_node('hello')\n",
853 "G.add_node('goodbye', fill=\"red\")\n",
854 "G.add_edges_from([(1,2),(1,3)])"
855 ],
856 "language": "python",
857 "metadata": {},
858 "outputs": [],
859 "prompt_number": 139
860 },
861 {
862 "cell_type": "code",
863 "collapsed": false,
864 "input": [
865 "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
988 "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
866 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
989 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
867 "floating_container.button_text = \"Render Window\"\n",
990 "floating_container.button_text = \"Render Window\"\n",
@@ -869,143 +992,242 b''
869 " 'width': '420px',\n",
992 " 'width': '420px',\n",
870 " 'height': '350px'}, selector='modal')\n",
993 " 'height': '350px'}, selector='modal')\n",
871 "\n",
994 "\n",
995 "G = EventfulGraph()\n",
872 "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n",
996 "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n",
873 "display(floating_container)"
997 "display(floating_container)"
874 ],
998 ],
875 "language": "python",
999 "language": "python",
876 "metadata": {},
1000 "metadata": {},
877 "outputs": [],
1001 "outputs": [],
878 "prompt_number": 140
1002 "prompt_number": 11
879 },
1003 },
880 {
1004 {
881 "cell_type": "code",
1005 "cell_type": "markdown",
882 "collapsed": false,
883 "input": [
884 "G.node['goodbye']['fill']"
885 ],
886 "language": "python",
887 "metadata": {},
1006 "metadata": {},
888 "outputs": [
1007 "source": [
889 {
1008 "The following code creates an animation of some of the plot's properties."
890 "metadata": {},
1009 ]
891 "output_type": "pyout",
892 "prompt_number": 141,
893 "text": [
894 "'red'"
895 ]
896 }
897 ],
898 "prompt_number": 141
899 },
1010 },
900 {
1011 {
901 "cell_type": "code",
1012 "cell_type": "code",
902 "collapsed": false,
1013 "collapsed": false,
903 "input": [
1014 "input": [
904 "G.node['goodbye']['fill'] = 'grey'\n",
1015 "import time\n",
905 "G.node['goodbye']['stroke'] = 'red'\n",
1016 "\n",
906 "G.node['goodbye']['strokewidth'] = '4px'"
1017 "G.add_node(1, fill=\"red\", stroke=\"black\")\n",
1018 "time.sleep(1.0)\n",
1019 "\n",
1020 "G.add_node(2, fill=\"gold\", stroke=\"black\")\n",
1021 "time.sleep(1.0)\n",
1022 "\n",
1023 "G.add_node(3, fill=\"green\", stroke=\"black\")\n",
1024 "time.sleep(1.0)\n",
1025 "\n",
1026 "G.add_edges_from([(1,2),(1,3), (2,3)], stroke=\"#aaa\", strokewidth=\"1px\", distance=200, strength=0.5)\n",
1027 "time.sleep(1.0)\n",
1028 "\n",
1029 "G.adj[1][2]['distance'] = 20\n",
1030 "time.sleep(1.0)\n",
1031 "\n",
1032 "G.adj[1][3]['distance'] = 20\n",
1033 "time.sleep(1.0)\n",
1034 "\n",
1035 "G.adj[2][3]['distance'] = 20\n",
1036 "time.sleep(1.0)\n",
1037 "\n",
1038 "G.node[1]['r'] = 16\n",
1039 "time.sleep(0.3)\n",
1040 "G.node[1]['r'] = 8\n",
1041 "G.node[2]['r'] = 16\n",
1042 "time.sleep(0.3)\n",
1043 "G.node[2]['r'] = 8\n",
1044 "G.node[3]['r'] = 16\n",
1045 "time.sleep(0.3)\n",
1046 "G.node[3]['r'] = 8\n",
1047 "\n",
1048 "G.node[1]['fill'] = 'purple'\n",
1049 "time.sleep(0.3)\n",
1050 "G.node[1]['fill'] = 'red'\n",
1051 "G.node[2]['fill'] = 'purple'\n",
1052 "time.sleep(0.3)\n",
1053 "G.node[2]['fill'] = 'gold'\n",
1054 "G.node[3]['fill'] = 'purple'\n",
1055 "time.sleep(0.3)\n",
1056 "G.node[3]['fill'] = 'green'\n",
1057 "time.sleep(1.0)\n",
1058 "\n",
1059 "G.node.clear()\n",
1060 "time.sleep(1.0)\n",
1061 "\n",
1062 "floating_container.close()\n"
907 ],
1063 ],
908 "language": "python",
1064 "language": "python",
909 "metadata": {},
1065 "metadata": {},
910 "outputs": [],
1066 "outputs": [],
911 "prompt_number": 142
1067 "prompt_number": 12
912 },
1068 },
913 {
1069 {
914 "cell_type": "code",
1070 "cell_type": "heading",
915 "collapsed": false,
1071 "level": 2,
916 "input": [
917 "G.add_node('beep')\n",
918 "G.add_node('beep2')"
919 ],
920 "language": "python",
921 "metadata": {},
1072 "metadata": {},
922 "outputs": [],
1073 "source": [
923 "prompt_number": 143
1074 "Twitter Tweet Watcher"
1075 ]
924 },
1076 },
925 {
1077 {
926 "cell_type": "code",
1078 "cell_type": "markdown",
927 "collapsed": false,
928 "input": [
929 "G.remove_node('goodbye')"
930 ],
931 "language": "python",
932 "metadata": {},
1079 "metadata": {},
933 "outputs": [],
1080 "source": [
934 "prompt_number": 144
1081 "This example requires the Python \"twitter\" library to be installed (https://github.com/sixohsix/twitter). You can install Python twitter by running `sudo pip install twitter` or `sudo easy_install twitter` from the commandline."
1082 ]
935 },
1083 },
936 {
1084 {
937 "cell_type": "code",
1085 "cell_type": "code",
938 "collapsed": false,
1086 "collapsed": false,
939 "input": [
1087 "input": [
1088 "from twitter import *\n",
1089 "import time, datetime\n",
1090 "import math\n",
940 "\n",
1091 "\n",
941 "G.add_edges_from([(4,5),(4,6)], stroke=\"lime\", strokewidth=\"3px\")"
1092 "twitter_timestamp_format = \"%a %b %d %X %z %Y\""
942 ],
1093 ],
943 "language": "python",
1094 "language": "python",
944 "metadata": {},
1095 "metadata": {},
945 "outputs": [],
1096 "outputs": [],
946 "prompt_number": 145
1097 "prompt_number": 13
947 },
1098 },
948 {
1099 {
949 "cell_type": "code",
1100 "cell_type": "code",
950 "collapsed": false,
1101 "collapsed": false,
951 "input": [
1102 "input": [
952 "import time\n",
1103 "# Sign on to twitter.\n",
953 "for i in range(30):\n",
1104 "auth = OAuth(\n",
954 " G.add_edges_from([(7+i, 8+i), (7+i, 9+i)])\n",
1105 " consumer_key='iQvYfTfuD86fgVWGjPY0UA',\n",
955 " time.sleep(0.1)"
1106 " consumer_secret='C3jjP6vzYzTYoHV4s5NYPGuRkpT5SulKRKTkRmYg',\n",
1107 " token='2218195843-cOPQa0D1Yk3JbvjvsCa0tIYzBOEWxINekmGcEql',\n",
1108 " token_secret='3BFncT1zAvJRN6rj8haCxveZVLZWZ23QeulxzByXWlfoO'\n",
1109 ")\n",
1110 "twitter = Twitter(auth = auth)\n",
1111 "twitter_stream = TwitterStream(auth = auth, block = False)"
956 ],
1112 ],
957 "language": "python",
1113 "language": "python",
958 "metadata": {},
1114 "metadata": {},
959 "outputs": [],
1115 "outputs": [],
960 "prompt_number": 115
1116 "prompt_number": 14
961 },
1117 },
962 {
1118 {
963 "cell_type": "code",
1119 "cell_type": "code",
964 "collapsed": false,
1120 "collapsed": false,
965 "input": [
1121 "input": [
1122 "widget_container = widgets.ContainerWidget()\n",
1123 "widget_container.hbox()\n",
1124 "floating_container = widgets.ContainerWidget(parent=widget_container, default_view_name='ModalView')\n",
1125 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
1126 "floating_container.button_text = \"Render Window\"\n",
1127 "floating_container.set_css({\n",
1128 " 'width': '620px',\n",
1129 " 'height': '450px'}, selector='modal')\n",
966 "\n",
1130 "\n",
967 "for i in range(31):\n",
1131 "graph = EventfulGraph()\n",
968 " G.node[i+8]['fill'] = 'lime'\n",
1132 "d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
969 " G.node[i+7]['fill'] = 'blue'\n",
1133 "d3.width = 600\n",
970 " time.sleep(0.1)"
1134 "d3.height = 400\n",
971 ],
972 "language": "python",
973 "metadata": {},
974 "outputs": [],
975 "prompt_number": 116
976 },
977 {
978 "cell_type": "code",
979 "collapsed": false,
980 "input": [
981 "\n",
1135 "\n",
982 "for i in range(30):\n",
1136 "stop_button = widgets.ButtonWidget(parent=widget_container, description=\"Stop\")\n",
983 " G.add_edge(7, i+8)\n",
1137 "stop_button.set_css('margin-left', '5px')\n",
984 " time.sleep(0.25)"
1138 " \n",
1139 "# Only listen to tweets while they are available and the user\n",
1140 "# doesn't want to stop.\n",
1141 "stop_listening = [False]\n",
1142 "def handle_stop():\n",
1143 " stop_listening[0] = True\n",
1144 " print(\"Service stopped\")\n",
1145 "stop_button.on_click(handle_stop)\n",
1146 "\n",
1147 "def watch_tweets(screen_name=None):\n",
1148 " display(widget_container)\n",
1149 " graph.node.clear()\n",
1150 " graph.adj.clear()\n",
1151 " start_timestamp = None\n",
1152 " stop_button.add_class('btn-danger')\n",
1153 " \n",
1154 " # Get Barack's tweets\n",
1155 " tweets = twitter.statuses.user_timeline(screen_name=screen_name)\n",
1156 " user_id = twitter.users.lookup(screen_name=screen_name)[0]['id']\n",
1157 " \n",
1158 " # Determine the maximum number of retweets.\n",
1159 " max_retweets = 0.0\n",
1160 " for tweet in tweets:\n",
1161 " max_retweets = float(max(tweet['retweet_count'], max_retweets))\n",
1162 " \n",
1163 " \n",
1164 " def plot_tweet(tweet, parent=None, elapsed_seconds=1.0, color=\"gold\"):\n",
1165 " new_id = tweet['id']\n",
1166 " graph.add_node(\n",
1167 " new_id, \n",
1168 " r=max(float(tweet['retweet_count']) / max_retweets * 30.0, 3.0),\n",
1169 " charge=-60,\n",
1170 " fill = color,\n",
1171 " )\n",
1172 " \n",
1173 " if parent is not None:\n",
1174 " parent_radius = max(float(parent['retweet_count']) / max_retweets * 30.0, 3.0)\n",
1175 " graph.node[parent['id']]['r'] = parent_radius\n",
1176 " \n",
1177 " graph.add_edge(new_id, parent['id'], distance=math.log(elapsed_seconds) * 9.0 + parent_radius)\n",
1178 " graph.node[new_id]['fill'] = 'red'\n",
1179 " \n",
1180 " \n",
1181 " # Plot each tweet.\n",
1182 " for tweet in tweets:\n",
1183 " plot_tweet(tweet)\n",
1184 " \n",
1185 " kernel=get_ipython().kernel\n",
1186 " iterator = twitter_stream.statuses.filter(follow=user_id)\n",
1187 " \n",
1188 " while not stop_listening[0]:\n",
1189 " kernel.do_one_iteration()\n",
1190 " \n",
1191 " for tweet in iterator:\n",
1192 " kernel.do_one_iteration()\n",
1193 " if stop_listening[0] or tweet is None:\n",
1194 " break\n",
1195 " else:\n",
1196 " if 'retweeted_status' in tweet:\n",
1197 " original_tweet = tweet['retweeted_status']\n",
1198 " if original_tweet['id'] in graph.node:\n",
1199 " tweet_timestamp = datetime.datetime.strptime(tweet['created_at'], twitter_timestamp_format) \n",
1200 " if start_timestamp is None:\n",
1201 " start_timestamp = tweet_timestamp\n",
1202 " elapsed_seconds = max((tweet_timestamp - start_timestamp).total_seconds(),1.0)\n",
1203 " \n",
1204 " plot_tweet(tweet, parent=original_tweet, elapsed_seconds=elapsed_seconds)\n",
1205 " elif 'id' in tweet:\n",
1206 " plot_tweet(tweet, color='lime')\n"
985 ],
1207 ],
986 "language": "python",
1208 "language": "python",
987 "metadata": {},
1209 "metadata": {},
988 "outputs": [],
1210 "outputs": [],
989 "prompt_number": 108
1211 "prompt_number": 15
990 },
1212 },
991 {
1213 {
992 "cell_type": "code",
1214 "cell_type": "code",
993 "collapsed": false,
1215 "collapsed": false,
994 "input": [
1216 "input": [
995 "G.clear()"
1217 "watch_tweets(screen_name=\"justinbieber\")"
996 ],
1218 ],
997 "language": "python",
1219 "language": "python",
998 "metadata": {},
1220 "metadata": {},
999 "outputs": [],
1221 "outputs": [
1000 "prompt_number": 47
1222 {
1001 },
1223 "output_type": "stream",
1002 {
1224 "stream": "stdout",
1003 "cell_type": "code",
1225 "text": [
1004 "collapsed": false,
1226 "Service stopped\n"
1005 "input": [],
1227 ]
1006 "language": "python",
1228 }
1007 "metadata": {},
1229 ],
1008 "outputs": []
1230 "prompt_number": 16
1009 }
1231 }
1010 ],
1232 ],
1011 "metadata": {}
1233 "metadata": {}
General Comments 0
You need to be logged in to leave comments. Login now