##// END OF EJS Templates
update example notebooks
Jason Grout -
Show More
@@ -1,1358 +1,1581 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": ""
4 },
4 },
5 "nbformat": 3,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 "nbformat_minor": 0,
7 "worksheets": [
7 "worksheets": [
8 {
8 {
9 "cells": [
9 "cells": [
10 {
10 {
11 "cell_type": "code",
11 "cell_type": "code",
12 "collapsed": false,
12 "collapsed": false,
13 "input": [
13 "input": [
14 "from __future__ import print_function # py 2.7 compat\n",
14 "from __future__ import print_function # py 2.7 compat\n",
15 "\n",
15 "\n",
16 "import networkx as nx"
16 "import networkx as nx"
17 ],
17 ],
18 "language": "python",
18 "language": "python",
19 "metadata": {},
19 "metadata": {},
20 "outputs": [],
20 "outputs": [],
21 "prompt_number": 1
21 "prompt_number": 1
22 },
22 },
23 {
23 {
24 "cell_type": "markdown",
24 "cell_type": "markdown",
25 "metadata": {},
25 "metadata": {},
26 "source": [
26 "source": [
27 "This notebook demonstrates how NetworkX and D3 can be married using custom widget code."
27 "This notebook demonstrates how NetworkX and D3 can be married using custom widget code."
28 ]
28 ]
29 },
29 },
30 {
30 {
31 "cell_type": "heading",
31 "cell_type": "heading",
32 "level": 1,
32 "level": 1,
33 "metadata": {},
33 "metadata": {},
34 "source": [
34 "source": [
35 "Hooking NetworkX Graphs"
35 "Hooking NetworkX Graphs"
36 ]
36 ]
37 },
37 },
38 {
38 {
39 "cell_type": "markdown",
39 "cell_type": "markdown",
40 "metadata": {},
40 "metadata": {},
41 "source": [
41 "source": [
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."
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."
43 ]
43 ]
44 },
44 },
45 {
45 {
46 "cell_type": "code",
46 "cell_type": "code",
47 "collapsed": false,
47 "collapsed": false,
48 "input": [
48 "input": [
49 "class EventfulDict(dict):\n",
49 "class EventfulDict(dict):\n",
50 " \n",
50 " \n",
51 " def __init__(self, *args, **kwargs):\n",
51 " def __init__(self, *args, **kwargs):\n",
52 " self._add_callbacks = []\n",
52 " self._add_callbacks = []\n",
53 " self._del_callbacks = []\n",
53 " self._del_callbacks = []\n",
54 " self._set_callbacks = []\n",
54 " self._set_callbacks = []\n",
55 " dict.__init__(self, *args, **kwargs)\n",
55 " dict.__init__(self, *args, **kwargs)\n",
56 " \n",
56 " \n",
57 " def on_add(self, callback, remove=False):\n",
57 " def on_add(self, callback, remove=False):\n",
58 " self._register_callback(self._add_callbacks, callback, remove)\n",
58 " self._register_callback(self._add_callbacks, callback, remove)\n",
59 " def on_del(self, callback, remove=False):\n",
59 " def on_del(self, callback, remove=False):\n",
60 " self._register_callback(self._del_callbacks, callback, remove)\n",
60 " self._register_callback(self._del_callbacks, callback, remove)\n",
61 " def on_set(self, callback, remove=False):\n",
61 " def on_set(self, callback, remove=False):\n",
62 " self._register_callback(self._set_callbacks, callback, remove)\n",
62 " self._register_callback(self._set_callbacks, callback, remove)\n",
63 " def _register_callback(self, callback_list, callback, remove=False):\n",
63 " def _register_callback(self, callback_list, callback, remove=False):\n",
64 " if callable(callback):\n",
64 " if callable(callback):\n",
65 " if remove and callback in callback_list:\n",
65 " if remove and callback in callback_list:\n",
66 " callback_list.remove(callback)\n",
66 " callback_list.remove(callback)\n",
67 " elif not remove and not callback in callback_list:\n",
67 " elif not remove and not callback in callback_list:\n",
68 " callback_list.append(callback)\n",
68 " callback_list.append(callback)\n",
69 " else:\n",
69 " else:\n",
70 " raise Exception('Callback must be callable.')\n",
70 " raise Exception('Callback must be callable.')\n",
71 "\n",
71 "\n",
72 " def _handle_add(self, key, value):\n",
72 " def _handle_add(self, key, value):\n",
73 " self._try_callbacks(self._add_callbacks, key, value)\n",
73 " self._try_callbacks(self._add_callbacks, key, value)\n",
74 " def _handle_del(self, key):\n",
74 " def _handle_del(self, key):\n",
75 " self._try_callbacks(self._del_callbacks, key)\n",
75 " self._try_callbacks(self._del_callbacks, key)\n",
76 " def _handle_set(self, key, value):\n",
76 " def _handle_set(self, key, value):\n",
77 " self._try_callbacks(self._set_callbacks, key, value)\n",
77 " self._try_callbacks(self._set_callbacks, key, value)\n",
78 " def _try_callbacks(self, callback_list, *pargs, **kwargs):\n",
78 " def _try_callbacks(self, callback_list, *pargs, **kwargs):\n",
79 " for callback in callback_list:\n",
79 " for callback in callback_list:\n",
80 " callback(*pargs, **kwargs)\n",
80 " callback(*pargs, **kwargs)\n",
81 " \n",
81 " \n",
82 " def __setitem__(self, key, value):\n",
82 " def __setitem__(self, key, value):\n",
83 " return_val = None\n",
83 " return_val = None\n",
84 " exists = False\n",
84 " exists = False\n",
85 " if key in self:\n",
85 " if key in self:\n",
86 " exists = True\n",
86 " exists = True\n",
87 " \n",
87 " \n",
88 " # If the user sets the property to a new dict, make the dict\n",
88 " # If the user sets the property to a new dict, make the dict\n",
89 " # eventful and listen to the changes of it ONLY if it is not\n",
89 " # eventful and listen to the changes of it ONLY if it is not\n",
90 " # already eventful. Any modification to this new dict will\n",
90 " # already eventful. Any modification to this new dict will\n",
91 " # fire a set event of the parent dict.\n",
91 " # fire a set event of the parent dict.\n",
92 " if isinstance(value, dict) and not isinstance(value, EventfulDict):\n",
92 " if isinstance(value, dict) and not isinstance(value, EventfulDict):\n",
93 " new_dict = EventfulDict(value)\n",
93 " new_dict = EventfulDict(value)\n",
94 " \n",
94 " \n",
95 " def handle_change(*pargs, **kwargs):\n",
95 " def handle_change(*pargs, **kwargs):\n",
96 " self._try_callbacks(self._set_callbacks, key, dict.__getitem__(self, key))\n",
96 " self._try_callbacks(self._set_callbacks, key, dict.__getitem__(self, key))\n",
97 " \n",
97 " \n",
98 " new_dict.on_add(handle_change)\n",
98 " new_dict.on_add(handle_change)\n",
99 " new_dict.on_del(handle_change)\n",
99 " new_dict.on_del(handle_change)\n",
100 " new_dict.on_set(handle_change)\n",
100 " new_dict.on_set(handle_change)\n",
101 " return_val = dict.__setitem__(self, key, new_dict)\n",
101 " return_val = dict.__setitem__(self, key, new_dict)\n",
102 " else:\n",
102 " else:\n",
103 " return_val = dict.__setitem__(self, key, value)\n",
103 " return_val = dict.__setitem__(self, key, value)\n",
104 " \n",
104 " \n",
105 " if exists:\n",
105 " if exists:\n",
106 " self._handle_set(key, value)\n",
106 " self._handle_set(key, value)\n",
107 " else:\n",
107 " else:\n",
108 " self._handle_add(key, value)\n",
108 " self._handle_add(key, value)\n",
109 " return return_val\n",
109 " return return_val\n",
110 " \n",
110 " \n",
111 "\n",
111 "\n",
112 " def __delitem__(self, key):\n",
112 " def __delitem__(self, key):\n",
113 " return_val = dict.__delitem__(self, key)\n",
113 " return_val = dict.__delitem__(self, key)\n",
114 " self._handle_del(key)\n",
114 " self._handle_del(key)\n",
115 " return return_val\n",
115 " return return_val\n",
116 "\n",
116 "\n",
117 " \n",
117 " \n",
118 " def pop(self, key):\n",
118 " def pop(self, key):\n",
119 " return_val = dict.pop(self, key)\n",
119 " return_val = dict.pop(self, key)\n",
120 " if key in self:\n",
120 " if key in self:\n",
121 " self._handle_del(key)\n",
121 " self._handle_del(key)\n",
122 " return return_val\n",
122 " return return_val\n",
123 "\n",
123 "\n",
124 " def popitem(self):\n",
124 " def popitem(self):\n",
125 " popped = dict.popitem(self)\n",
125 " popped = dict.popitem(self)\n",
126 " if popped is not None and popped[0] is not None:\n",
126 " if popped is not None and popped[0] is not None:\n",
127 " self._handle_del(popped[0])\n",
127 " self._handle_del(popped[0])\n",
128 " return popped\n",
128 " return popped\n",
129 "\n",
129 "\n",
130 " def update(self, other_dict):\n",
130 " def update(self, other_dict):\n",
131 " for (key, value) in other_dict.items():\n",
131 " for (key, value) in other_dict.items():\n",
132 " self[key] = value\n",
132 " self[key] = value\n",
133 " \n",
133 " \n",
134 " def clear(self):\n",
134 " def clear(self):\n",
135 " for key in list(self.keys()):\n",
135 " for key in list(self.keys()):\n",
136 " del self[key]"
136 " del self[key]"
137 ],
137 ],
138 "language": "python",
138 "language": "python",
139 "metadata": {},
139 "metadata": {},
140 "outputs": [],
140 "outputs": [],
141 "prompt_number": 2
141 "prompt_number": 2
142 },
142 },
143 {
143 {
144 "cell_type": "markdown",
144 "cell_type": "markdown",
145 "metadata": {},
145 "metadata": {},
146 "source": [
146 "source": [
147 "Override the NetworkX Graph object to make an eventful graph."
147 "Override the NetworkX Graph object to make an eventful graph."
148 ]
148 ]
149 },
149 },
150 {
150 {
151 "cell_type": "code",
151 "cell_type": "code",
152 "collapsed": false,
152 "collapsed": false,
153 "input": [
153 "input": [
154 "class EventfulGraph(nx.Graph):\n",
154 "class EventfulGraph(nx.Graph):\n",
155 " \n",
155 " \n",
156 " def __init__(self, *pargs, **kwargs):\n",
156 " def __init__(self, *pargs, **kwargs):\n",
157 " \"\"\"Initialize a graph with edges, name, graph attributes.\"\"\"\n",
157 " \"\"\"Initialize a graph with edges, name, graph attributes.\"\"\"\n",
158 " super(EventfulGraph, self).__init__(*pargs, **kwargs)\n",
158 " super(EventfulGraph, self).__init__(*pargs, **kwargs)\n",
159 " \n",
159 " \n",
160 " self.graph = EventfulDict(self.graph)\n",
160 " self.graph = EventfulDict(self.graph)\n",
161 " self.node = EventfulDict(self.node)\n",
161 " self.node = EventfulDict(self.node)\n",
162 " self.adj = EventfulDict(self.adj)\n",
162 " self.adj = EventfulDict(self.adj)\n",
163 " "
163 " "
164 ],
164 ],
165 "language": "python",
165 "language": "python",
166 "metadata": {},
166 "metadata": {},
167 "outputs": [],
167 "outputs": [],
168 "prompt_number": 3
168 "prompt_number": 3
169 },
169 },
170 {
170 {
171 "cell_type": "markdown",
171 "cell_type": "markdown",
172 "metadata": {},
172 "metadata": {},
173 "source": [
173 "source": [
174 "To make sure that the eventful graph works, create a new graph and log the dictionary events raised."
174 "To make sure that the eventful graph works, create a new graph and log the dictionary events raised."
175 ]
175 ]
176 },
176 },
177 {
177 {
178 "cell_type": "code",
178 "cell_type": "code",
179 "collapsed": false,
179 "collapsed": false,
180 "input": [
180 "input": [
181 "def echo_dict_events(eventful_dict, prefix=''):\n",
181 "def echo_dict_events(eventful_dict, prefix=''):\n",
182 " def key_add(key, value):\n",
182 " def key_add(key, value):\n",
183 " print(prefix + 'add (%s, %s)' % (key, str(value)))\n",
183 " print(prefix + 'add (%s, %s)' % (key, str(value)))\n",
184 " def key_set(key, value):\n",
184 " def key_set(key, value):\n",
185 " print(prefix + 'set (%s, %s)' % (key, str(value)))\n",
185 " print(prefix + 'set (%s, %s)' % (key, str(value)))\n",
186 " def key_del(key):\n",
186 " def key_del(key):\n",
187 " print(prefix + 'del %s' % key)\n",
187 " print(prefix + 'del %s' % key)\n",
188 " eventful_dict.on_add(key_add)\n",
188 " eventful_dict.on_add(key_add)\n",
189 " eventful_dict.on_set(key_set)\n",
189 " eventful_dict.on_set(key_set)\n",
190 " eventful_dict.on_del(key_del)\n",
190 " eventful_dict.on_del(key_del)\n",
191 " \n",
191 " \n",
192 "def echo_graph_events(eventful_graph):\n",
192 "def echo_graph_events(eventful_graph):\n",
193 " for key in ['graph', 'node', 'adj']:\n",
193 " for key in ['graph', 'node', 'adj']:\n",
194 " echo_dict_events(getattr(eventful_graph, key), prefix=key+' ')"
194 " echo_dict_events(getattr(eventful_graph, key), prefix=key+' ')"
195 ],
195 ],
196 "language": "python",
196 "language": "python",
197 "metadata": {},
197 "metadata": {},
198 "outputs": [],
198 "outputs": [],
199 "prompt_number": 4
199 "prompt_number": 4
200 },
200 },
201 {
201 {
202 "cell_type": "code",
202 "cell_type": "code",
203 "collapsed": false,
203 "collapsed": false,
204 "input": [
204 "input": [
205 "G = EventfulGraph()\n",
205 "G = EventfulGraph()\n",
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', fill=\"red\")\n",
209 "G.add_node('goodbye', fill=\"red\")\n",
210 "G.add_edges_from([(1,2),(1,3), (1,'goodbye')], stroke=\"lime\")"
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": {},
214 "outputs": [
214 "outputs": [
215 {
215 {
216 "output_type": "stream",
216 "output_type": "stream",
217 "stream": "stdout",
217 "stream": "stdout",
218 "text": [
218 "text": [
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, {'fill': '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: {'stroke': 'lime'}})\n",
227 "adj set (1, {2: {'stroke': 'lime'}})\n",
228 "adj set (2, {1: {'stroke': 'lime'}})\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: {'stroke': 'lime'}, 3: {'stroke': 'lime'}})\n",
231 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}})\n",
232 "adj set (3, {1: {'stroke': 'lime'}})\n",
232 "adj set (3, {1: {'stroke': 'lime'}})\n",
233 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
233 "adj set (1, {2: {'stroke': 'lime'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
234 "adj set (goodbye, {1: {'stroke': 'lime'}})\n"
234 "adj set (goodbye, {1: {'stroke': 'lime'}})\n"
235 ]
235 ]
236 }
236 }
237 ],
237 ],
238 "prompt_number": 5
238 "prompt_number": 5
239 },
239 },
240 {
240 {
241 "cell_type": "code",
241 "cell_type": "code",
242 "collapsed": false,
242 "collapsed": false,
243 "input": [
243 "input": [
244 "G.adj"
244 "G.adj"
245 ],
245 ],
246 "language": "python",
246 "language": "python",
247 "metadata": {},
247 "metadata": {},
248 "outputs": [
248 "outputs": [
249 {
249 {
250 "metadata": {},
250 "metadata": {},
251 "output_type": "pyout",
251 "output_type": "pyout",
252 "prompt_number": 6,
252 "prompt_number": 6,
253 "text": [
253 "text": [
254 "{1: {2: {'stroke': 'lime'},\n",
254 "{1: {2: {'stroke': 'lime'},\n",
255 " 3: {'stroke': 'lime'},\n",
255 " 3: {'stroke': 'lime'},\n",
256 " 'goodbye': {'stroke': 'lime'}},\n",
256 " 'goodbye': {'stroke': 'lime'}},\n",
257 " 2: {1: {'stroke': 'lime'}},\n",
257 " 2: {1: {'stroke': 'lime'}},\n",
258 " 3: {1: {'stroke': 'lime'}},\n",
258 " 3: {1: {'stroke': 'lime'}},\n",
259 " 'goodbye': {1: {'stroke': 'lime'}},\n",
259 " 'goodbye': {1: {'stroke': 'lime'}},\n",
260 " 'hello': {}}"
260 " 'hello': {}}"
261 ]
261 ]
262 }
262 }
263 ],
263 ],
264 "prompt_number": 6
264 "prompt_number": 6
265 },
265 },
266 {
266 {
267 "cell_type": "code",
267 "cell_type": "code",
268 "collapsed": false,
268 "collapsed": false,
269 "input": [
269 "input": [
270 "G.node"
270 "G.node"
271 ],
271 ],
272 "language": "python",
272 "language": "python",
273 "metadata": {},
273 "metadata": {},
274 "outputs": [
274 "outputs": [
275 {
275 {
276 "metadata": {},
276 "metadata": {},
277 "output_type": "pyout",
277 "output_type": "pyout",
278 "prompt_number": 7,
278 "prompt_number": 7,
279 "text": [
279 "text": [
280 "{1: {}, 2: {}, 3: {}, 'goodbye': {'fill': 'red'}, 'hello': {}}"
280 "{1: {}, 2: {}, 3: {}, 'goodbye': {'fill': 'red'}, 'hello': {}}"
281 ]
281 ]
282 }
282 }
283 ],
283 ],
284 "prompt_number": 7
284 "prompt_number": 7
285 },
285 },
286 {
286 {
287 "cell_type": "heading",
287 "cell_type": "heading",
288 "level": 1,
288 "level": 1,
289 "metadata": {},
289 "metadata": {},
290 "source": [
290 "source": [
291 "D3 Widget"
291 "D3 Widget"
292 ]
292 ]
293 },
293 },
294 {
294 {
295 "cell_type": "markdown",
295 "cell_type": "markdown",
296 "metadata": {},
296 "metadata": {},
297 "source": [
297 "source": [
298 "The D3 widget will blindly port all of the dictionary events over custom widget messages."
298 "The D3 widget will blindly port all of the dictionary events over custom widget messages."
299 ]
299 ]
300 },
300 },
301 {
301 {
302 "cell_type": "code",
302 "cell_type": "code",
303 "collapsed": false,
303 "collapsed": false,
304 "input": [
304 "input": [
305 "from IPython.html import widgets # Widget definitions\n",
305 "from IPython.html import widgets # Widget definitions\n",
306 "from IPython.display import display # Used to display widgets in the notebook"
306 "from IPython.display import display # Used to display widgets in the notebook"
307 ],
307 ],
308 "language": "python",
308 "language": "python",
309 "metadata": {},
309 "metadata": {},
310 "outputs": [],
310 "outputs": [],
311 "prompt_number": 8
311 "prompt_number": 8
312 },
312 },
313 {
313 {
314 "cell_type": "code",
314 "cell_type": "code",
315 "collapsed": false,
315 "collapsed": false,
316 "input": [
316 "input": [
317 "# Import the base Widget class and the traitlets Unicode class.\n",
317 "# Import the base Widget class and the traitlets Unicode class.\n",
318 "from IPython.html.widgets import Widget\n",
318 "from IPython.html.widgets import Widget\n",
319 "from IPython.utils.traitlets import Unicode, Int\n",
319 "from IPython.utils.traitlets import Unicode, Int\n",
320 "\n",
320 "\n",
321 "# Define our ForceDirectedGraphWidget and its target model and default view.\n",
321 "# Define our ForceDirectedGraphWidget and its target model and default view.\n",
322 "class ForceDirectedGraphWidget(Widget):\n",
322 "class ForceDirectedGraphWidget(Widget):\n",
323 " target_name = Unicode('ForceDirectedGraphModel')\n",
323 " target_name = Unicode('ForceDirectedGraphModel')\n",
324 " default_view_name = Unicode('D3ForceDirectedGraphView')\n",
324 " default_view_name = Unicode('D3ForceDirectedGraphView')\n",
325 " \n",
325 " \n",
326 " _keys = ['width', 'height']\n",
326 " _keys = ['width', 'height']\n",
327 " width = Int(400)\n",
327 " width = Int(400)\n",
328 " height = Int(300)\n",
328 " height = Int(300)\n",
329 " \n",
329 " \n",
330 " def __init__(self, eventful_graph, *pargs, **kwargs):\n",
330 " def __init__(self, eventful_graph, *pargs, **kwargs):\n",
331 " Widget.__init__(self, *pargs, **kwargs)\n",
331 " Widget.__init__(self, *pargs, **kwargs)\n",
332 " \n",
332 " \n",
333 " self._eventful_graph = eventful_graph\n",
333 " self._eventful_graph = eventful_graph\n",
334 " self._send_dict_changes(eventful_graph.graph, 'graph')\n",
334 " self._send_dict_changes(eventful_graph.graph, 'graph')\n",
335 " self._send_dict_changes(eventful_graph.node, 'node')\n",
335 " self._send_dict_changes(eventful_graph.node, 'node')\n",
336 " self._send_dict_changes(eventful_graph.adj, 'adj')\n",
336 " self._send_dict_changes(eventful_graph.adj, 'adj')\n",
337 " \n",
337 " \n",
338 " \n",
338 " \n",
339 " def _repr_widget_(self, *pargs, **kwargs):\n",
339 " def _repr_widget_(self, *pargs, **kwargs):\n",
340 " \n",
340 " \n",
341 " # Show the widget, then send the current state\n",
341 " # Show the widget, then send the current state\n",
342 " Widget._repr_widget_(self, *pargs, **kwargs)\n",
342 " Widget._repr_widget_(self, *pargs, **kwargs)\n",
343 " for (key, value) in self._eventful_graph.graph.items():\n",
343 " for (key, value) in self._eventful_graph.graph.items():\n",
344 " self.send({'dict': 'graph', 'action': 'add', 'key': key, 'value': value})\n",
344 " self.send({'dict': 'graph', 'action': 'add', 'key': key, 'value': value})\n",
345 " for (key, value) in self._eventful_graph.node.items():\n",
345 " for (key, value) in self._eventful_graph.node.items():\n",
346 " self.send({'dict': 'node', 'action': 'add', 'key': key, 'value': value})\n",
346 " self.send({'dict': 'node', 'action': 'add', 'key': key, 'value': value})\n",
347 " for (key, value) in self._eventful_graph.adj.items():\n",
347 " for (key, value) in self._eventful_graph.adj.items():\n",
348 " self.send({'dict': 'adj', 'action': 'add', 'key': key, 'value': value})\n",
348 " self.send({'dict': 'adj', 'action': 'add', 'key': key, 'value': value})\n",
349 " \n",
349 " \n",
350 " \n",
350 " \n",
351 " def _send_dict_changes(self, eventful_dict, dict_name):\n",
351 " def _send_dict_changes(self, eventful_dict, dict_name):\n",
352 " def key_add(key, value):\n",
352 " def key_add(key, value):\n",
353 " self.send({'dict': dict_name, 'action': 'add', 'key': key, 'value': value})\n",
353 " self.send({'dict': dict_name, 'action': 'add', 'key': key, 'value': value})\n",
354 " def key_set(key, value):\n",
354 " def key_set(key, value):\n",
355 " self.send({'dict': dict_name, 'action': 'set', 'key': key, 'value': value})\n",
355 " self.send({'dict': dict_name, 'action': 'set', 'key': key, 'value': value})\n",
356 " def key_del(key):\n",
356 " def key_del(key):\n",
357 " self.send({'dict': dict_name, 'action': 'del', 'key': key})\n",
357 " self.send({'dict': dict_name, 'action': 'del', 'key': key})\n",
358 " eventful_dict.on_add(key_add)\n",
358 " eventful_dict.on_add(key_add)\n",
359 " eventful_dict.on_set(key_set)\n",
359 " eventful_dict.on_set(key_set)\n",
360 " eventful_dict.on_del(key_del)\n",
360 " eventful_dict.on_del(key_del)\n",
361 " "
361 " "
362 ],
362 ],
363 "language": "python",
363 "language": "python",
364 "metadata": {},
364 "metadata": {},
365 "outputs": [],
365 "outputs": [],
366 "prompt_number": 9
366 "prompt_number": 9
367 },
367 },
368 {
368 {
369 "cell_type": "markdown",
369 "cell_type": "markdown",
370 "metadata": {},
370 "metadata": {},
371 "source": [
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."
372 "The front-end listens to the dictionary events and keeps the D3 control in sync with the dictionary in the back-end."
373 ]
373 ]
374 },
374 },
375 {
375 {
376 "cell_type": "code",
376 "cell_type": "code",
377 "collapsed": false,
377 "collapsed": false,
378 "input": [
378 "input": [
379 "%%javascript\n",
379 "%%javascript\n",
380 "\n",
380 "\n",
381 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
381 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
382 " \n",
382 " \n",
383 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
383 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
384 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
384 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
385 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
385 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
386 " \n",
386 " \n",
387 " // Define the D3ForceDirectedGraphView\n",
387 " // Define the D3ForceDirectedGraphView\n",
388 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
388 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
389 " \n",
389 " \n",
390 " render: function(){\n",
390 " render: function(){\n",
391 " this.guid = 'd3force' + IPython.utils.uuid();\n",
391 " this.guid = 'd3force' + IPython.utils.uuid();\n",
392 " this.setElement($('<div />', {id: this.guid}));\n",
392 " this.setElement($('<div />', {id: this.guid}));\n",
393 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
393 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
394 " this.has_drawn = false;\n",
394 " this.has_drawn = false;\n",
395 " },\n",
395 " },\n",
396 " \n",
396 " \n",
397 " try_add_node: function(id){\n",
397 " try_add_node: function(id){\n",
398 " var index = this.find_node(id);\n",
398 " var index = this.find_node(id);\n",
399 " if (index == -1) {\n",
399 " if (index == -1) {\n",
400 " var node = {id: id};\n",
400 " var node = {id: id};\n",
401 " this.nodes.push(node);\n",
401 " this.nodes.push(node);\n",
402 " return node;\n",
402 " return node;\n",
403 " } else {\n",
403 " } else {\n",
404 " return this.nodes[index];\n",
404 " return this.nodes[index];\n",
405 " }\n",
405 " }\n",
406 " },\n",
406 " },\n",
407 " \n",
407 " \n",
408 " update_node: function(node, attributes) {\n",
408 " update_node: function(node, attributes) {\n",
409 " if (node !== null) {\n",
409 " if (node !== null) {\n",
410 " for (var key in attributes) {\n",
410 " for (var key in attributes) {\n",
411 " node[key] = attributes[key];\n",
411 " node[key] = attributes[key];\n",
412 " }\n",
412 " }\n",
413 " this._update_node(d3.select('#' + this.guid + node.id));\n",
413 " this._update_node(d3.select('#' + this.guid + node.id));\n",
414 " }\n",
414 " }\n",
415 " },\n",
415 " },\n",
416 " \n",
416 " \n",
417 " remove_node: function(id){\n",
417 " remove_node: function(id){\n",
418 " this.remove_links_to(id);\n",
418 " this.remove_links_to(id);\n",
419 " \n",
419 " \n",
420 " var found_index = this.find_node(id);\n",
420 " var found_index = this.find_node(id);\n",
421 " if (found_index>=0) {\n",
421 " if (found_index>=0) {\n",
422 " this.nodes.splice(found_index, 1);\n",
422 " this.nodes.splice(found_index, 1);\n",
423 " }\n",
423 " }\n",
424 " },\n",
424 " },\n",
425 " \n",
425 " \n",
426 " find_node: function(id){\n",
426 " find_node: function(id){\n",
427 " var found_index = -1;\n",
427 " var found_index = -1;\n",
428 " for (var index in this.nodes) {\n",
428 " for (var index in this.nodes) {\n",
429 " if (this.nodes[index].id == id) {\n",
429 " if (this.nodes[index].id == id) {\n",
430 " found_index = index;\n",
430 " found_index = index;\n",
431 " break;\n",
431 " break;\n",
432 " }\n",
432 " }\n",
433 " }\n",
433 " }\n",
434 " return found_index;\n",
434 " return found_index;\n",
435 " },\n",
435 " },\n",
436 " \n",
436 " \n",
437 " find_link: function(source_id, target_id){\n",
437 " find_link: function(source_id, target_id){\n",
438 " for (var index in this.links) {\n",
438 " for (var index in this.links) {\n",
439 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
439 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
440 " return index;\n",
440 " return index;\n",
441 " }\n",
441 " }\n",
442 " }\n",
442 " }\n",
443 " return -1;\n",
443 " return -1;\n",
444 " },\n",
444 " },\n",
445 " \n",
445 " \n",
446 " try_add_link: function(source_id, target_id){\n",
446 " try_add_link: function(source_id, target_id){\n",
447 " var index = this.find_link(source_id, target_id);\n",
447 " var index = this.find_link(source_id, target_id);\n",
448 " if (index == -1) {\n",
448 " if (index == -1) {\n",
449 " var source_node = this.try_add_node(source_id);\n",
449 " var source_node = this.try_add_node(source_id);\n",
450 " var target_node = this.try_add_node(target_id);\n",
450 " var target_node = this.try_add_node(target_id);\n",
451 " var new_link = {source: source_node, target: target_node};\n",
451 " var new_link = {source: source_node, target: target_node};\n",
452 " this.links.push(new_link);\n",
452 " this.links.push(new_link);\n",
453 " return new_link;\n",
453 " return new_link;\n",
454 " } else {\n",
454 " } else {\n",
455 " return this.links[index]\n",
455 " return this.links[index]\n",
456 " }\n",
456 " }\n",
457 " },\n",
457 " },\n",
458 " \n",
458 " \n",
459 " update_link: function(link, attributes){\n",
459 " update_link: function(link, attributes){\n",
460 " if (link != null) {\n",
460 " if (link != null) {\n",
461 " for (var key in attributes) {\n",
461 " for (var key in attributes) {\n",
462 " link[key] = attributes[key];\n",
462 " link[key] = attributes[key];\n",
463 " }\n",
463 " }\n",
464 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
464 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
465 " }\n",
465 " }\n",
466 " },\n",
466 " },\n",
467 " \n",
467 " \n",
468 " remove_links: function(source_id){\n",
468 " remove_links: function(source_id){\n",
469 " var found_indicies = [];\n",
469 " var found_indicies = [];\n",
470 " for (var index in this.links) {\n",
470 " for (var index in this.links) {\n",
471 " if (this.links[index].source.id == source_id) {\n",
471 " if (this.links[index].source.id == source_id) {\n",
472 " found_indicies.push(index);\n",
472 " found_indicies.push(index);\n",
473 " }\n",
473 " }\n",
474 " }\n",
474 " }\n",
475 " found_indicies.reverse();\n",
475 " found_indicies.reverse();\n",
476 " \n",
476 " \n",
477 " for (var index in found_indicies) {\n",
477 " for (var index in found_indicies) {\n",
478 " this.links.splice(index, 1);\n",
478 " this.links.splice(index, 1);\n",
479 " };\n",
479 " };\n",
480 " },\n",
480 " },\n",
481 " \n",
481 " \n",
482 " remove_links_to: function(id){\n",
482 " remove_links_to: function(id){\n",
483 " var found_indicies = [];\n",
483 " var found_indicies = [];\n",
484 " for (var index in this.links) {\n",
484 " for (var index in this.links) {\n",
485 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
485 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
486 " found_indicies.push(index);\n",
486 " found_indicies.push(index);\n",
487 " }\n",
487 " }\n",
488 " }\n",
488 " }\n",
489 " found_indicies.reverse();\n",
489 " found_indicies.reverse();\n",
490 " \n",
490 " \n",
491 " for (var index in found_indicies) {\n",
491 " for (var index in found_indicies) {\n",
492 " this.links.splice(index, 1);\n",
492 " this.links.splice(index, 1);\n",
493 " };\n",
493 " };\n",
494 " },\n",
494 " },\n",
495 " \n",
495 " \n",
496 " handle_msg: function(content){\n",
496 " handle_msg: function(content){\n",
497 " var dict = content.dict;\n",
497 " var dict = content.dict;\n",
498 " var action = content.action;\n",
498 " var action = content.action;\n",
499 " var key = content.key;\n",
499 " var key = content.key;\n",
500 " \n",
500 " \n",
501 " if (dict=='node') {\n",
501 " if (dict=='node') {\n",
502 " if (action=='add' || action=='set') {\n",
502 " if (action=='add' || action=='set') {\n",
503 " this.update_node(this.try_add_node(key), content.value)\n",
503 " this.update_node(this.try_add_node(key), content.value)\n",
504 " } else if (action=='del') {\n",
504 " } else if (action=='del') {\n",
505 " this.remove_node(key);\n",
505 " this.remove_node(key);\n",
506 " }\n",
506 " }\n",
507 " \n",
507 " \n",
508 " } else if (dict=='adj') {\n",
508 " } else if (dict=='adj') {\n",
509 " if (action=='add' || action=='set') {\n",
509 " if (action=='add' || action=='set') {\n",
510 " var links = content.value;\n",
510 " var links = content.value;\n",
511 " for (var target_id in links) {\n",
511 " for (var target_id in links) {\n",
512 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
512 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
513 " }\n",
513 " }\n",
514 " } else if (action=='del') {\n",
514 " } else if (action=='del') {\n",
515 " this.remove_links(key);\n",
515 " this.remove_links(key);\n",
516 " }\n",
516 " }\n",
517 " }\n",
517 " }\n",
518 " this.start();\n",
518 " this.start();\n",
519 " },\n",
519 " },\n",
520 " \n",
520 " \n",
521 " start: function() {\n",
521 " start: function() {\n",
522 " var node = this.svg.selectAll(\".node\"),\n",
522 " var node = this.svg.selectAll(\".node\"),\n",
523 " link = this.svg.selectAll(\".link\");\n",
523 " link = this.svg.selectAll(\".link\");\n",
524 " \n",
524 " \n",
525 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
525 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
526 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
526 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
527 " link.exit().remove();\n",
527 " link.exit().remove();\n",
528 " \n",
528 " \n",
529 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
529 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
530 " var that = this;\n",
530 " var that = this;\n",
531 " this._update_node(node.enter().append(\"circle\"));\n",
531 " this._update_node(node.enter().append(\"circle\"));\n",
532 " node.exit().remove();\n",
532 " node.exit().remove();\n",
533 " \n",
533 " \n",
534 " this.force.start();\n",
534 " this.force.start();\n",
535 " },\n",
535 " },\n",
536 " \n",
536 " \n",
537 " _update_node: function(node) {\n",
537 " _update_node: function(node) {\n",
538 " var that = this;\n",
538 " var that = this;\n",
539 " node\n",
539 " node\n",
540 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
540 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
541 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
541 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
542 " .attr(\"r\", function(d) {\n",
542 " .attr(\"r\", function(d) {\n",
543 " if (d.r == undefined) {\n",
543 " if (d.r == undefined) {\n",
544 " return 8; \n",
544 " return 8; \n",
545 " } else {\n",
545 " } else {\n",
546 " return d.r;\n",
546 " return d.r;\n",
547 " }\n",
547 " }\n",
548 " \n",
548 " \n",
549 " })\n",
549 " })\n",
550 " .style(\"fill\", function(d) {\n",
550 " .style(\"fill\", function(d) {\n",
551 " if (d.fill == undefined) {\n",
551 " if (d.fill == undefined) {\n",
552 " return that.color(d.group); \n",
552 " return that.color(d.group); \n",
553 " } else {\n",
553 " } else {\n",
554 " return d.fill;\n",
554 " return d.fill;\n",
555 " }\n",
555 " }\n",
556 " \n",
556 " \n",
557 " })\n",
557 " })\n",
558 " .style(\"stroke\", function(d) {\n",
558 " .style(\"stroke\", function(d) {\n",
559 " if (d.stroke == undefined) {\n",
559 " if (d.stroke == undefined) {\n",
560 " return \"#FFF\"; \n",
560 " return \"#FFF\"; \n",
561 " } else {\n",
561 " } else {\n",
562 " return d.stroke;\n",
562 " return d.stroke;\n",
563 " }\n",
563 " }\n",
564 " \n",
564 " \n",
565 " })\n",
565 " })\n",
566 " .style(\"stroke-width\", function(d) {\n",
566 " .style(\"stroke-width\", function(d) {\n",
567 " if (d.strokewidth == undefined) {\n",
567 " if (d.strokewidth == undefined) {\n",
568 " return \"#FFF\"; \n",
568 " return \"#FFF\"; \n",
569 " } else {\n",
569 " } else {\n",
570 " return d.strokewidth;\n",
570 " return d.strokewidth;\n",
571 " }\n",
571 " }\n",
572 " \n",
572 " \n",
573 " })\n",
573 " })\n",
574 " .call(this.force.drag);\n",
574 " .call(this.force.drag);\n",
575 " },\n",
575 " },\n",
576 " \n",
576 " \n",
577 " _update_edge: function(edge) {\n",
577 " _update_edge: function(edge) {\n",
578 " var that = this;\n",
578 " var that = this;\n",
579 " edge\n",
579 " edge\n",
580 " .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",
581 " .attr(\"class\", \"link\")\n",
581 " .attr(\"class\", \"link\")\n",
582 " .style(\"stroke-width\", function(d) {\n",
582 " .style(\"stroke-width\", function(d) {\n",
583 " if (d.strokewidth == undefined) {\n",
583 " if (d.strokewidth == undefined) {\n",
584 " return \"1.5px\"; \n",
584 " return \"1.5px\"; \n",
585 " } else {\n",
585 " } else {\n",
586 " return d.strokewidth;\n",
586 " return d.strokewidth;\n",
587 " }\n",
587 " }\n",
588 " \n",
588 " \n",
589 " })\n",
589 " })\n",
590 " .style('stroke', function(d) {\n",
590 " .style('stroke', function(d) {\n",
591 " if (d.stroke == undefined) {\n",
591 " if (d.stroke == undefined) {\n",
592 " return \"#999\"; \n",
592 " return \"#999\"; \n",
593 " } else {\n",
593 " } else {\n",
594 " return d.stroke;\n",
594 " return d.stroke;\n",
595 " }\n",
595 " }\n",
596 " \n",
596 " \n",
597 " });\n",
597 " });\n",
598 " },\n",
598 " },\n",
599 " \n",
599 " \n",
600 " tick: function() {\n",
600 " tick: function() {\n",
601 " var node = this.svg.selectAll(\".node\"),\n",
601 " var node = this.svg.selectAll(\".node\"),\n",
602 " link = this.svg.selectAll(\".link\");\n",
602 " link = this.svg.selectAll(\".link\");\n",
603 " \n",
603 " \n",
604 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
604 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
605 " .attr(\"y1\", function(d) { return d.source.y; })\n",
605 " .attr(\"y1\", function(d) { return d.source.y; })\n",
606 " .attr(\"x2\", function(d) { return d.target.x; })\n",
606 " .attr(\"x2\", function(d) { return d.target.x; })\n",
607 " .attr(\"y2\", function(d) { return d.target.y; });\n",
607 " .attr(\"y2\", function(d) { return d.target.y; });\n",
608 " \n",
608 " \n",
609 " node.attr(\"cx\", function(d) { return d.x; })\n",
609 " node.attr(\"cx\", function(d) { return d.x; })\n",
610 " .attr(\"cy\", function(d) { return d.y; });\n",
610 " .attr(\"cy\", function(d) { return d.y; });\n",
611 " },\n",
611 " },\n",
612 " \n",
612 " \n",
613 " update: function(){\n",
613 " update: function(){\n",
614 " if (!this.has_drawn) {\n",
614 " if (!this.has_drawn) {\n",
615 " this.has_drawn = true;\n",
615 " this.has_drawn = true;\n",
616 " \n",
616 " \n",
617 " var width = this.model.get('width'),\n",
617 " var width = this.model.get('width'),\n",
618 " height = this.model.get('height');\n",
618 " height = this.model.get('height');\n",
619 " \n",
619 " \n",
620 " this.color = d3.scale.category20();\n",
620 " this.color = d3.scale.category20();\n",
621 " \n",
621 " \n",
622 " this.nodes = [];\n",
622 " this.nodes = [];\n",
623 " this.links = [];\n",
623 " this.links = [];\n",
624 " \n",
624 " \n",
625 " this.force = d3.layout.force()\n",
625 " this.force = d3.layout.force()\n",
626 " .nodes(this.nodes)\n",
626 " .nodes(this.nodes)\n",
627 " .links(this.links)\n",
627 " .links(this.links)\n",
628 " .charge(function (d) {\n",
628 " .charge(function (d) {\n",
629 " if (d.charge === undefined) {\n",
629 " if (d.charge === undefined) {\n",
630 " return -120;\n",
630 " return -120;\n",
631 " } else {\n",
631 " } else {\n",
632 " return d.charge;\n",
632 " return d.charge;\n",
633 " }\n",
633 " }\n",
634 " })\n",
634 " })\n",
635 " .linkDistance(function (d) {\n",
635 " .linkDistance(function (d) {\n",
636 " if (d.distance === undefined) {\n",
636 " if (d.distance === undefined) {\n",
637 " return 40;\n",
637 " return 40;\n",
638 " } else {\n",
638 " } else {\n",
639 " return d.distance;\n",
639 " return d.distance;\n",
640 " }\n",
640 " }\n",
641 " })\n",
641 " })\n",
642 " .linkStrength(function (d) {\n",
642 " .linkStrength(function (d) {\n",
643 " if (d.strength === undefined) {\n",
643 " if (d.strength === undefined) {\n",
644 " return 1.0;\n",
644 " return 1.0;\n",
645 " } else {\n",
645 " } else {\n",
646 " return d.strength;\n",
646 " return d.strength;\n",
647 " }\n",
647 " }\n",
648 " })\n",
648 " })\n",
649 " .size([width, height])\n",
649 " .size([width, height])\n",
650 " .on(\"tick\", $.proxy(this.tick, this));\n",
650 " .on(\"tick\", $.proxy(this.tick, this));\n",
651 " \n",
651 " \n",
652 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
652 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
653 " .attr(\"width\", width)\n",
653 " .attr(\"width\", width)\n",
654 " .attr(\"height\", height);\n",
654 " .attr(\"height\", height);\n",
655 " \n",
655 " \n",
656 " var that = this;\n",
656 " var that = this;\n",
657 " setTimeout(function() {\n",
657 " setTimeout(function() {\n",
658 " that.start();\n",
658 " that.start();\n",
659 " }, 0);\n",
659 " }, 0);\n",
660 " }\n",
660 " }\n",
661 " \n",
661 " \n",
662 " return IPython.WidgetView.prototype.update.call(this);\n",
662 " return IPython.WidgetView.prototype.update.call(this);\n",
663 " },\n",
663 " },\n",
664 " \n",
664 " \n",
665 " });\n",
665 " });\n",
666 " \n",
666 " \n",
667 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
667 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
668 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
668 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
669 "});"
669 "});"
670 ],
670 ],
671 "language": "python",
671 "language": "python",
672 "metadata": {},
672 "metadata": {},
673 "outputs": [
673 "outputs": [
674 {
674 {
675 "javascript": [
675 "javascript": [
676 "\n",
676 "\n",
677 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
677 "require([\"http://d3js.org/d3.v3.min.js\", \"notebook/js/widget\"], function(){\n",
678 " \n",
678 " \n",
679 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
679 " // Define the ForceDirectedGraphModel and register it with the widget manager.\n",
680 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
680 " var ForceDirectedGraphModel = IPython.WidgetModel.extend({});\n",
681 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
681 " IPython.widget_manager.register_widget_model('ForceDirectedGraphModel', ForceDirectedGraphModel);\n",
682 " \n",
682 " \n",
683 " // Define the D3ForceDirectedGraphView\n",
683 " // Define the D3ForceDirectedGraphView\n",
684 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
684 " var D3ForceDirectedGraphView = IPython.WidgetView.extend({\n",
685 " \n",
685 " \n",
686 " render: function(){\n",
686 " render: function(){\n",
687 " this.guid = 'd3force' + IPython.utils.uuid();\n",
687 " this.guid = 'd3force' + IPython.utils.uuid();\n",
688 " this.setElement($('<div />', {id: this.guid}));\n",
688 " this.setElement($('<div />', {id: this.guid}));\n",
689 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
689 " this.model.on_msg($.proxy(this.handle_msg, this));\n",
690 " this.has_drawn = false;\n",
690 " this.has_drawn = false;\n",
691 " },\n",
691 " },\n",
692 " \n",
692 " \n",
693 " try_add_node: function(id){\n",
693 " try_add_node: function(id){\n",
694 " var index = this.find_node(id);\n",
694 " var index = this.find_node(id);\n",
695 " if (index == -1) {\n",
695 " if (index == -1) {\n",
696 " var node = {id: id};\n",
696 " var node = {id: id};\n",
697 " this.nodes.push(node);\n",
697 " this.nodes.push(node);\n",
698 " return node;\n",
698 " return node;\n",
699 " } else {\n",
699 " } else {\n",
700 " return this.nodes[index];\n",
700 " return this.nodes[index];\n",
701 " }\n",
701 " }\n",
702 " },\n",
702 " },\n",
703 " \n",
703 " \n",
704 " update_node: function(node, attributes) {\n",
704 " update_node: function(node, attributes) {\n",
705 " if (node !== null) {\n",
705 " if (node !== null) {\n",
706 " for (var key in attributes) {\n",
706 " for (var key in attributes) {\n",
707 " node[key] = attributes[key];\n",
707 " node[key] = attributes[key];\n",
708 " }\n",
708 " }\n",
709 " this._update_node(d3.select('#' + this.guid + node.id));\n",
709 " this._update_node(d3.select('#' + this.guid + node.id));\n",
710 " }\n",
710 " }\n",
711 " },\n",
711 " },\n",
712 " \n",
712 " \n",
713 " remove_node: function(id){\n",
713 " remove_node: function(id){\n",
714 " this.remove_links_to(id);\n",
714 " this.remove_links_to(id);\n",
715 " \n",
715 " \n",
716 " var found_index = this.find_node(id);\n",
716 " var found_index = this.find_node(id);\n",
717 " if (found_index>=0) {\n",
717 " if (found_index>=0) {\n",
718 " this.nodes.splice(found_index, 1);\n",
718 " this.nodes.splice(found_index, 1);\n",
719 " }\n",
719 " }\n",
720 " },\n",
720 " },\n",
721 " \n",
721 " \n",
722 " find_node: function(id){\n",
722 " find_node: function(id){\n",
723 " var found_index = -1;\n",
723 " var found_index = -1;\n",
724 " for (var index in this.nodes) {\n",
724 " for (var index in this.nodes) {\n",
725 " if (this.nodes[index].id == id) {\n",
725 " if (this.nodes[index].id == id) {\n",
726 " found_index = index;\n",
726 " found_index = index;\n",
727 " break;\n",
727 " break;\n",
728 " }\n",
728 " }\n",
729 " }\n",
729 " }\n",
730 " return found_index;\n",
730 " return found_index;\n",
731 " },\n",
731 " },\n",
732 " \n",
732 " \n",
733 " find_link: function(source_id, target_id){\n",
733 " find_link: function(source_id, target_id){\n",
734 " for (var index in this.links) {\n",
734 " for (var index in this.links) {\n",
735 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
735 " if (this.links[index].source.id == source_id && this.links[index].target.id == target_id) {\n",
736 " return index;\n",
736 " return index;\n",
737 " }\n",
737 " }\n",
738 " }\n",
738 " }\n",
739 " return -1;\n",
739 " return -1;\n",
740 " },\n",
740 " },\n",
741 " \n",
741 " \n",
742 " try_add_link: function(source_id, target_id){\n",
742 " try_add_link: function(source_id, target_id){\n",
743 " var index = this.find_link(source_id, target_id);\n",
743 " var index = this.find_link(source_id, target_id);\n",
744 " if (index == -1) {\n",
744 " if (index == -1) {\n",
745 " var source_node = this.try_add_node(source_id);\n",
745 " var source_node = this.try_add_node(source_id);\n",
746 " var target_node = this.try_add_node(target_id);\n",
746 " var target_node = this.try_add_node(target_id);\n",
747 " var new_link = {source: source_node, target: target_node};\n",
747 " var new_link = {source: source_node, target: target_node};\n",
748 " this.links.push(new_link);\n",
748 " this.links.push(new_link);\n",
749 " return new_link;\n",
749 " return new_link;\n",
750 " } else {\n",
750 " } else {\n",
751 " return this.links[index]\n",
751 " return this.links[index]\n",
752 " }\n",
752 " }\n",
753 " },\n",
753 " },\n",
754 " \n",
754 " \n",
755 " update_link: function(link, attributes){\n",
755 " update_link: function(link, attributes){\n",
756 " if (link != null) {\n",
756 " if (link != null) {\n",
757 " for (var key in attributes) {\n",
757 " for (var key in attributes) {\n",
758 " link[key] = attributes[key];\n",
758 " link[key] = attributes[key];\n",
759 " }\n",
759 " }\n",
760 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
760 " this._update_edge(d3.select('#' + this.guid + link.source.id + \"-\" + link.target.id));\n",
761 " }\n",
761 " }\n",
762 " },\n",
762 " },\n",
763 " \n",
763 " \n",
764 " remove_links: function(source_id){\n",
764 " remove_links: function(source_id){\n",
765 " var found_indicies = [];\n",
765 " var found_indicies = [];\n",
766 " for (var index in this.links) {\n",
766 " for (var index in this.links) {\n",
767 " if (this.links[index].source.id == source_id) {\n",
767 " if (this.links[index].source.id == source_id) {\n",
768 " found_indicies.push(index);\n",
768 " found_indicies.push(index);\n",
769 " }\n",
769 " }\n",
770 " }\n",
770 " }\n",
771 " found_indicies.reverse();\n",
771 " found_indicies.reverse();\n",
772 " \n",
772 " \n",
773 " for (var index in found_indicies) {\n",
773 " for (var index in found_indicies) {\n",
774 " this.links.splice(index, 1);\n",
774 " this.links.splice(index, 1);\n",
775 " };\n",
775 " };\n",
776 " },\n",
776 " },\n",
777 " \n",
777 " \n",
778 " remove_links_to: function(id){\n",
778 " remove_links_to: function(id){\n",
779 " var found_indicies = [];\n",
779 " var found_indicies = [];\n",
780 " for (var index in this.links) {\n",
780 " for (var index in this.links) {\n",
781 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
781 " if (this.links[index].source.id == id || this.links[index].target.id == id) {\n",
782 " found_indicies.push(index);\n",
782 " found_indicies.push(index);\n",
783 " }\n",
783 " }\n",
784 " }\n",
784 " }\n",
785 " found_indicies.reverse();\n",
785 " found_indicies.reverse();\n",
786 " \n",
786 " \n",
787 " for (var index in found_indicies) {\n",
787 " for (var index in found_indicies) {\n",
788 " this.links.splice(index, 1);\n",
788 " this.links.splice(index, 1);\n",
789 " };\n",
789 " };\n",
790 " },\n",
790 " },\n",
791 " \n",
791 " \n",
792 " handle_msg: function(content){\n",
792 " handle_msg: function(content){\n",
793 " var dict = content.dict;\n",
793 " var dict = content.dict;\n",
794 " var action = content.action;\n",
794 " var action = content.action;\n",
795 " var key = content.key;\n",
795 " var key = content.key;\n",
796 " \n",
796 " \n",
797 " if (dict=='node') {\n",
797 " if (dict=='node') {\n",
798 " if (action=='add' || action=='set') {\n",
798 " if (action=='add' || action=='set') {\n",
799 " this.update_node(this.try_add_node(key), content.value)\n",
799 " this.update_node(this.try_add_node(key), content.value)\n",
800 " } else if (action=='del') {\n",
800 " } else if (action=='del') {\n",
801 " this.remove_node(key);\n",
801 " this.remove_node(key);\n",
802 " }\n",
802 " }\n",
803 " \n",
803 " \n",
804 " } else if (dict=='adj') {\n",
804 " } else if (dict=='adj') {\n",
805 " if (action=='add' || action=='set') {\n",
805 " if (action=='add' || action=='set') {\n",
806 " var links = content.value;\n",
806 " var links = content.value;\n",
807 " for (var target_id in links) {\n",
807 " for (var target_id in links) {\n",
808 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
808 " this.update_link(this.try_add_link(key, target_id), links[target_id]);\n",
809 " }\n",
809 " }\n",
810 " } else if (action=='del') {\n",
810 " } else if (action=='del') {\n",
811 " this.remove_links(key);\n",
811 " this.remove_links(key);\n",
812 " }\n",
812 " }\n",
813 " }\n",
813 " }\n",
814 " this.start();\n",
814 " this.start();\n",
815 " },\n",
815 " },\n",
816 " \n",
816 " \n",
817 " start: function() {\n",
817 " start: function() {\n",
818 " var node = this.svg.selectAll(\".node\"),\n",
818 " var node = this.svg.selectAll(\".node\"),\n",
819 " link = this.svg.selectAll(\".link\");\n",
819 " link = this.svg.selectAll(\".link\");\n",
820 " \n",
820 " \n",
821 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
821 " var link = link.data(this.force.links(), function(d) { return d.source.id + \"-\" + d.target.id; });\n",
822 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
822 " this._update_edge(link.enter().insert(\"line\", \".node\"))\n",
823 " link.exit().remove();\n",
823 " link.exit().remove();\n",
824 " \n",
824 " \n",
825 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
825 " var node = node.data(this.force.nodes(), function(d) { return d.id;});\n",
826 " var that = this;\n",
826 " var that = this;\n",
827 " this._update_node(node.enter().append(\"circle\"));\n",
827 " this._update_node(node.enter().append(\"circle\"));\n",
828 " node.exit().remove();\n",
828 " node.exit().remove();\n",
829 " \n",
829 " \n",
830 " this.force.start();\n",
830 " this.force.start();\n",
831 " },\n",
831 " },\n",
832 " \n",
832 " \n",
833 " _update_node: function(node) {\n",
833 " _update_node: function(node) {\n",
834 " var that = this;\n",
834 " var that = this;\n",
835 " node\n",
835 " node\n",
836 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
836 " .attr(\"id\", function(d) { return that.guid + d.id; })\n",
837 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
837 " .attr(\"class\", function(d) { return \"node \" + d.id; })\n",
838 " .attr(\"r\", function(d) {\n",
838 " .attr(\"r\", function(d) {\n",
839 " if (d.r == undefined) {\n",
839 " if (d.r == undefined) {\n",
840 " return 8; \n",
840 " return 8; \n",
841 " } else {\n",
841 " } else {\n",
842 " return d.r;\n",
842 " return d.r;\n",
843 " }\n",
843 " }\n",
844 " \n",
844 " \n",
845 " })\n",
845 " })\n",
846 " .style(\"fill\", function(d) {\n",
846 " .style(\"fill\", function(d) {\n",
847 " if (d.fill == undefined) {\n",
847 " if (d.fill == undefined) {\n",
848 " return that.color(d.group); \n",
848 " return that.color(d.group); \n",
849 " } else {\n",
849 " } else {\n",
850 " return d.fill;\n",
850 " return d.fill;\n",
851 " }\n",
851 " }\n",
852 " \n",
852 " \n",
853 " })\n",
853 " })\n",
854 " .style(\"stroke\", function(d) {\n",
854 " .style(\"stroke\", function(d) {\n",
855 " if (d.stroke == undefined) {\n",
855 " if (d.stroke == undefined) {\n",
856 " return \"#FFF\"; \n",
856 " return \"#FFF\"; \n",
857 " } else {\n",
857 " } else {\n",
858 " return d.stroke;\n",
858 " return d.stroke;\n",
859 " }\n",
859 " }\n",
860 " \n",
860 " \n",
861 " })\n",
861 " })\n",
862 " .style(\"stroke-width\", function(d) {\n",
862 " .style(\"stroke-width\", function(d) {\n",
863 " if (d.strokewidth == undefined) {\n",
863 " if (d.strokewidth == undefined) {\n",
864 " return \"#FFF\"; \n",
864 " return \"#FFF\"; \n",
865 " } else {\n",
865 " } else {\n",
866 " return d.strokewidth;\n",
866 " return d.strokewidth;\n",
867 " }\n",
867 " }\n",
868 " \n",
868 " \n",
869 " })\n",
869 " })\n",
870 " .call(this.force.drag);\n",
870 " .call(this.force.drag);\n",
871 " },\n",
871 " },\n",
872 " \n",
872 " \n",
873 " _update_edge: function(edge) {\n",
873 " _update_edge: function(edge) {\n",
874 " var that = this;\n",
874 " var that = this;\n",
875 " edge\n",
875 " edge\n",
876 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
876 " .attr(\"id\", function(d) { return that.guid + d.source.id + \"-\" + d.target.id; })\n",
877 " .attr(\"class\", \"link\")\n",
877 " .attr(\"class\", \"link\")\n",
878 " .style(\"stroke-width\", function(d) {\n",
878 " .style(\"stroke-width\", function(d) {\n",
879 " if (d.strokewidth == undefined) {\n",
879 " if (d.strokewidth == undefined) {\n",
880 " return \"1.5px\"; \n",
880 " return \"1.5px\"; \n",
881 " } else {\n",
881 " } else {\n",
882 " return d.strokewidth;\n",
882 " return d.strokewidth;\n",
883 " }\n",
883 " }\n",
884 " \n",
884 " \n",
885 " })\n",
885 " })\n",
886 " .style('stroke', function(d) {\n",
886 " .style('stroke', function(d) {\n",
887 " if (d.stroke == undefined) {\n",
887 " if (d.stroke == undefined) {\n",
888 " return \"#999\"; \n",
888 " return \"#999\"; \n",
889 " } else {\n",
889 " } else {\n",
890 " return d.stroke;\n",
890 " return d.stroke;\n",
891 " }\n",
891 " }\n",
892 " \n",
892 " \n",
893 " });\n",
893 " });\n",
894 " },\n",
894 " },\n",
895 " \n",
895 " \n",
896 " tick: function() {\n",
896 " tick: function() {\n",
897 " var node = this.svg.selectAll(\".node\"),\n",
897 " var node = this.svg.selectAll(\".node\"),\n",
898 " link = this.svg.selectAll(\".link\");\n",
898 " link = this.svg.selectAll(\".link\");\n",
899 " \n",
899 " \n",
900 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
900 " link.attr(\"x1\", function(d) { return d.source.x; })\n",
901 " .attr(\"y1\", function(d) { return d.source.y; })\n",
901 " .attr(\"y1\", function(d) { return d.source.y; })\n",
902 " .attr(\"x2\", function(d) { return d.target.x; })\n",
902 " .attr(\"x2\", function(d) { return d.target.x; })\n",
903 " .attr(\"y2\", function(d) { return d.target.y; });\n",
903 " .attr(\"y2\", function(d) { return d.target.y; });\n",
904 " \n",
904 " \n",
905 " node.attr(\"cx\", function(d) { return d.x; })\n",
905 " node.attr(\"cx\", function(d) { return d.x; })\n",
906 " .attr(\"cy\", function(d) { return d.y; });\n",
906 " .attr(\"cy\", function(d) { return d.y; });\n",
907 " },\n",
907 " },\n",
908 " \n",
908 " \n",
909 " update: function(){\n",
909 " update: function(){\n",
910 " if (!this.has_drawn) {\n",
910 " if (!this.has_drawn) {\n",
911 " this.has_drawn = true;\n",
911 " this.has_drawn = true;\n",
912 " \n",
912 " \n",
913 " var width = this.model.get('width'),\n",
913 " var width = this.model.get('width'),\n",
914 " height = this.model.get('height');\n",
914 " height = this.model.get('height');\n",
915 " \n",
915 " \n",
916 " this.color = d3.scale.category20();\n",
916 " this.color = d3.scale.category20();\n",
917 " \n",
917 " \n",
918 " this.nodes = [];\n",
918 " this.nodes = [];\n",
919 " this.links = [];\n",
919 " this.links = [];\n",
920 " \n",
920 " \n",
921 " this.force = d3.layout.force()\n",
921 " this.force = d3.layout.force()\n",
922 " .nodes(this.nodes)\n",
922 " .nodes(this.nodes)\n",
923 " .links(this.links)\n",
923 " .links(this.links)\n",
924 " .charge(function (d) {\n",
924 " .charge(function (d) {\n",
925 " if (d.charge === undefined) {\n",
925 " if (d.charge === undefined) {\n",
926 " return -120;\n",
926 " return -120;\n",
927 " } else {\n",
927 " } else {\n",
928 " return d.charge;\n",
928 " return d.charge;\n",
929 " }\n",
929 " }\n",
930 " })\n",
930 " })\n",
931 " .linkDistance(function (d) {\n",
931 " .linkDistance(function (d) {\n",
932 " if (d.distance === undefined) {\n",
932 " if (d.distance === undefined) {\n",
933 " return 40;\n",
933 " return 40;\n",
934 " } else {\n",
934 " } else {\n",
935 " return d.distance;\n",
935 " return d.distance;\n",
936 " }\n",
936 " }\n",
937 " })\n",
937 " })\n",
938 " .linkStrength(function (d) {\n",
938 " .linkStrength(function (d) {\n",
939 " if (d.strength === undefined) {\n",
939 " if (d.strength === undefined) {\n",
940 " return 1.0;\n",
940 " return 1.0;\n",
941 " } else {\n",
941 " } else {\n",
942 " return d.strength;\n",
942 " return d.strength;\n",
943 " }\n",
943 " }\n",
944 " })\n",
944 " })\n",
945 " .size([width, height])\n",
945 " .size([width, height])\n",
946 " .on(\"tick\", $.proxy(this.tick, this));\n",
946 " .on(\"tick\", $.proxy(this.tick, this));\n",
947 " \n",
947 " \n",
948 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
948 " this.svg = d3.select(\"#\" + this.guid).append(\"svg\")\n",
949 " .attr(\"width\", width)\n",
949 " .attr(\"width\", width)\n",
950 " .attr(\"height\", height);\n",
950 " .attr(\"height\", height);\n",
951 " \n",
951 " \n",
952 " var that = this;\n",
952 " var that = this;\n",
953 " setTimeout(function() {\n",
953 " setTimeout(function() {\n",
954 " that.start();\n",
954 " that.start();\n",
955 " }, 0);\n",
955 " }, 0);\n",
956 " }\n",
956 " }\n",
957 " \n",
957 " \n",
958 " return IPython.WidgetView.prototype.update.call(this);\n",
958 " return IPython.WidgetView.prototype.update.call(this);\n",
959 " },\n",
959 " },\n",
960 " \n",
960 " \n",
961 " });\n",
961 " });\n",
962 " \n",
962 " \n",
963 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
963 " // Register the D3ForceDirectedGraphView with the widget manager.\n",
964 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
964 " IPython.widget_manager.register_widget_view('D3ForceDirectedGraphView', D3ForceDirectedGraphView);\n",
965 "});"
965 "});"
966 ],
966 ],
967 "metadata": {},
967 "metadata": {},
968 "output_type": "display_data",
968 "output_type": "display_data",
969 "text": [
969 "text": [
970 "<IPython.core.display.Javascript at 0x2281b10>"
970 "<IPython.core.display.Javascript at 0x1100ddd50>"
971 ]
971 ]
972 }
972 }
973 ],
973 ],
974 "prompt_number": 10
974 "prompt_number": 10
975 },
975 },
976 {
976 {
977 "cell_type": "heading",
977 "cell_type": "heading",
978 "level": 1,
978 "level": 1,
979 "metadata": {},
979 "metadata": {},
980 "source": [
980 "source": [
981 "Test"
981 "Test"
982 ]
982 ]
983 },
983 },
984 {
984 {
985 "cell_type": "code",
985 "cell_type": "code",
986 "collapsed": false,
986 "collapsed": false,
987 "input": [
987 "input": [
988 "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
988 "floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
989 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
989 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
990 "floating_container.button_text = \"Render Window\"\n",
990 "floating_container.button_text = \"Render Window\"\n",
991 "floating_container.set_css({\n",
991 "floating_container.set_css({\n",
992 " 'width': '420px',\n",
992 " 'width': '420px',\n",
993 " 'height': '350px'}, selector='modal')\n",
993 " 'height': '350px'}, selector='modal')\n",
994 "\n",
994 "\n",
995 "G = EventfulGraph()\n",
995 "G = EventfulGraph()\n",
996 "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n",
996 "d3 = ForceDirectedGraphWidget(G, parent=floating_container)\n",
997 "display(floating_container)"
997 "display(floating_container)"
998 ],
998 ],
999 "language": "python",
999 "language": "python",
1000 "metadata": {},
1000 "metadata": {},
1001 "outputs": [],
1001 "outputs": [
1002 {
1003 "ename": "KeyError",
1004 "evalue": "'modal'",
1005 "output_type": "pyerr",
1006 "traceback": [
1007 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
1008 "\u001b[0;32m<ipython-input-11-3d50cedcbcf3>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m floating_container.set_css({\n\u001b[1;32m 5\u001b[0m \u001b[0;34m'width'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'420px'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m 'height': '350px'}, selector='modal')\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mG\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mEventfulGraph\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1009 "\u001b[0;32m/Users/grout/projects/ipython-upstream/IPython/html/widgets/widget.pyc\u001b[0m in \u001b[0;36mset_css\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 355\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 356\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 357\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_css\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mselector\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_css\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mselector\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 358\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_css\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mselector\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 359\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend_state\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'_css'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1010 "\u001b[0;31mKeyError\u001b[0m: 'modal'"
1011 ]
1012 }
1013 ],
1002 "prompt_number": 11
1014 "prompt_number": 11
1003 },
1015 },
1004 {
1016 {
1005 "cell_type": "markdown",
1017 "cell_type": "markdown",
1006 "metadata": {},
1018 "metadata": {},
1007 "source": [
1019 "source": [
1008 "The following code creates an animation of some of the plot's properties."
1020 "The following code creates an animation of some of the plot's properties."
1009 ]
1021 ]
1010 },
1022 },
1011 {
1023 {
1012 "cell_type": "code",
1024 "cell_type": "code",
1013 "collapsed": false,
1025 "collapsed": false,
1014 "input": [
1026 "input": [
1015 "import time\n",
1027 "import time\n",
1016 "\n",
1028 "\n",
1017 "G.add_node(1, fill=\"red\", stroke=\"black\")\n",
1029 "G.add_node(1, fill=\"red\", stroke=\"black\")\n",
1018 "time.sleep(1.0)\n",
1030 "time.sleep(1.0)\n",
1019 "\n",
1031 "\n",
1020 "G.add_node(2, fill=\"gold\", stroke=\"black\")\n",
1032 "G.add_node(2, fill=\"gold\", stroke=\"black\")\n",
1021 "time.sleep(1.0)\n",
1033 "time.sleep(1.0)\n",
1022 "\n",
1034 "\n",
1023 "G.add_node(3, fill=\"green\", stroke=\"black\")\n",
1035 "G.add_node(3, fill=\"green\", stroke=\"black\")\n",
1024 "time.sleep(1.0)\n",
1036 "time.sleep(1.0)\n",
1025 "\n",
1037 "\n",
1026 "G.add_edges_from([(1,2),(1,3), (2,3)], stroke=\"#aaa\", strokewidth=\"1px\", distance=200, strength=0.5)\n",
1038 "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",
1039 "time.sleep(1.0)\n",
1028 "\n",
1040 "\n",
1029 "G.adj[1][2]['distance'] = 20\n",
1041 "G.adj[1][2]['distance'] = 20\n",
1030 "time.sleep(1.0)\n",
1042 "time.sleep(1.0)\n",
1031 "\n",
1043 "\n",
1032 "G.adj[1][3]['distance'] = 20\n",
1044 "G.adj[1][3]['distance'] = 20\n",
1033 "time.sleep(1.0)\n",
1045 "time.sleep(1.0)\n",
1034 "\n",
1046 "\n",
1035 "G.adj[2][3]['distance'] = 20\n",
1047 "G.adj[2][3]['distance'] = 20\n",
1036 "time.sleep(1.0)\n",
1048 "time.sleep(1.0)\n",
1037 "\n",
1049 "\n",
1038 "G.node[1]['r'] = 16\n",
1050 "G.node[1]['r'] = 16\n",
1039 "time.sleep(0.3)\n",
1051 "time.sleep(0.3)\n",
1040 "G.node[1]['r'] = 8\n",
1052 "G.node[1]['r'] = 8\n",
1041 "G.node[2]['r'] = 16\n",
1053 "G.node[2]['r'] = 16\n",
1042 "time.sleep(0.3)\n",
1054 "time.sleep(0.3)\n",
1043 "G.node[2]['r'] = 8\n",
1055 "G.node[2]['r'] = 8\n",
1044 "G.node[3]['r'] = 16\n",
1056 "G.node[3]['r'] = 16\n",
1045 "time.sleep(0.3)\n",
1057 "time.sleep(0.3)\n",
1046 "G.node[3]['r'] = 8\n",
1058 "G.node[3]['r'] = 8\n",
1047 "\n",
1059 "\n",
1048 "G.node[1]['fill'] = 'purple'\n",
1060 "G.node[1]['fill'] = 'purple'\n",
1049 "time.sleep(0.3)\n",
1061 "time.sleep(0.3)\n",
1050 "G.node[1]['fill'] = 'red'\n",
1062 "G.node[1]['fill'] = 'red'\n",
1051 "G.node[2]['fill'] = 'purple'\n",
1063 "G.node[2]['fill'] = 'purple'\n",
1052 "time.sleep(0.3)\n",
1064 "time.sleep(0.3)\n",
1053 "G.node[2]['fill'] = 'gold'\n",
1065 "G.node[2]['fill'] = 'gold'\n",
1054 "G.node[3]['fill'] = 'purple'\n",
1066 "G.node[3]['fill'] = 'purple'\n",
1055 "time.sleep(0.3)\n",
1067 "time.sleep(0.3)\n",
1056 "G.node[3]['fill'] = 'green'\n",
1068 "G.node[3]['fill'] = 'green'\n",
1057 "time.sleep(1.0)\n",
1069 "time.sleep(1.0)\n",
1058 "\n",
1070 "\n",
1059 "G.node.clear()\n",
1071 "G.node.clear()\n",
1060 "time.sleep(1.0)\n",
1072 "time.sleep(1.0)\n",
1061 "\n",
1073 "\n",
1062 "floating_container.close()\n"
1074 "floating_container.close()\n"
1063 ],
1075 ],
1064 "language": "python",
1076 "language": "python",
1065 "metadata": {},
1077 "metadata": {},
1066 "outputs": [],
1078 "outputs": [
1079 {
1080 "output_type": "stream",
1081 "stream": "stdout",
1082 "text": [
1083 "node set (1, {'stroke': 'black'})\n",
1084 "node set (1, {'stroke': 'black', 'fill': 'red'})\n",
1085 "node set (2, {'stroke': 'black'})"
1086 ]
1087 },
1088 {
1089 "output_type": "stream",
1090 "stream": "stdout",
1091 "text": [
1092 "\n",
1093 "node set (2, {'stroke': 'black', 'fill': 'gold'})\n",
1094 "node set (3, {'stroke': 'black'})"
1095 ]
1096 },
1097 {
1098 "output_type": "stream",
1099 "stream": "stdout",
1100 "text": [
1101 "\n",
1102 "node set (3, {'stroke': 'black', 'fill': 'green'})\n",
1103 "adj set (1, {2: {'distance': 200, 'stroke': 'lime'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})"
1104 ]
1105 },
1106 {
1107 "output_type": "stream",
1108 "stream": "stdout",
1109 "text": [
1110 "\n",
1111 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
1112 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px'}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
1113 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
1114 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
1115 "adj set (2, {1: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}})\n",
1116 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': 'lime'}, 'goodbye': {'stroke': 'lime'}})\n",
1117 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': '#aaa'}, 'goodbye': {'stroke': 'lime'}})\n",
1118 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px'}, 'goodbye': {'stroke': 'lime'}})\n",
1119 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 'goodbye': {'stroke': 'lime'}})\n",
1120 "adj set (1, {2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 'goodbye': {'stroke': 'lime'}})\n",
1121 "adj set (3, {1: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}})\n",
1122 "adj set (2, {1: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}})\n",
1123 "adj set (3, {1: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 2: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}})\n",
1124 "adj set (1, {2: {'distance': 20, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 200, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 'goodbye': {'stroke': 'lime'}})"
1125 ]
1126 },
1127 {
1128 "output_type": "stream",
1129 "stream": "stdout",
1130 "text": [
1131 "\n",
1132 "adj set (1, {2: {'distance': 20, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 20, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 'goodbye': {'stroke': 'lime'}})"
1133 ]
1134 },
1135 {
1136 "output_type": "stream",
1137 "stream": "stdout",
1138 "text": [
1139 "\n",
1140 "adj set (2, {1: {'distance': 20, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}, 3: {'distance': 20, 'stroke': '#aaa', 'strokewidth': '1px', 'strength': 0.5}})"
1141 ]
1142 },
1143 {
1144 "output_type": "stream",
1145 "stream": "stdout",
1146 "text": [
1147 "\n",
1148 "node set (1, {'stroke': 'black', 'r': 16, 'fill': 'red'})"
1149 ]
1150 },
1151 {
1152 "output_type": "stream",
1153 "stream": "stdout",
1154 "text": [
1155 "\n",
1156 "node set (1, {'stroke': 'black', 'r': 8, 'fill': 'red'})"
1157 ]
1158 },
1159 {
1160 "output_type": "stream",
1161 "stream": "stdout",
1162 "text": [
1163 "\n",
1164 "node set (2, {'stroke': 'black', 'r': 16, 'fill': 'gold'})\n",
1165 "node set (2, {'stroke': 'black', 'r': 8, 'fill': 'gold'})"
1166 ]
1167 },
1168 {
1169 "output_type": "stream",
1170 "stream": "stdout",
1171 "text": [
1172 "\n",
1173 "node set (3, {'stroke': 'black', 'r': 16, 'fill': 'green'})\n",
1174 "node set (3, {'stroke': 'black', 'r': 8, 'fill': 'green'})"
1175 ]
1176 },
1177 {
1178 "output_type": "stream",
1179 "stream": "stdout",
1180 "text": [
1181 "\n",
1182 "node set (1, {'stroke': 'black', 'r': 8, 'fill': 'purple'})\n",
1183 "node set (1, {'stroke': 'black', 'r': 8, 'fill': 'red'})"
1184 ]
1185 },
1186 {
1187 "output_type": "stream",
1188 "stream": "stdout",
1189 "text": [
1190 "\n",
1191 "node set (2, {'stroke': 'black', 'r': 8, 'fill': 'purple'})\n",
1192 "node set (2, {'stroke': 'black', 'r': 8, 'fill': 'gold'})"
1193 ]
1194 },
1195 {
1196 "output_type": "stream",
1197 "stream": "stdout",
1198 "text": [
1199 "\n",
1200 "node set (3, {'stroke': 'black', 'r': 8, 'fill': 'purple'})\n",
1201 "node set (3, {'stroke': 'black', 'r': 8, 'fill': 'green'})"
1202 ]
1203 },
1204 {
1205 "output_type": "stream",
1206 "stream": "stdout",
1207 "text": [
1208 "\n",
1209 "node del 1"
1210 ]
1211 },
1212 {
1213 "output_type": "stream",
1214 "stream": "stdout",
1215 "text": [
1216 "\n",
1217 "node del 2\n",
1218 "node del 3\n",
1219 "node del hello\n",
1220 "node del goodbye\n"
1221 ]
1222 }
1223 ],
1067 "prompt_number": 12
1224 "prompt_number": 12
1068 },
1225 },
1069 {
1226 {
1070 "cell_type": "heading",
1227 "cell_type": "heading",
1071 "level": 2,
1228 "level": 2,
1072 "metadata": {},
1229 "metadata": {},
1073 "source": [
1230 "source": [
1074 "Prime Factor Finder"
1231 "Prime Factor Finder"
1075 ]
1232 ]
1076 },
1233 },
1077 {
1234 {
1078 "cell_type": "markdown",
1235 "cell_type": "markdown",
1079 "metadata": {},
1236 "metadata": {},
1080 "source": [
1237 "source": [
1081 "Find the prime numbers inside a large integer"
1238 "Find the prime numbers inside a large integer"
1082 ]
1239 ]
1083 },
1240 },
1084 {
1241 {
1085 "cell_type": "code",
1242 "cell_type": "code",
1086 "collapsed": false,
1243 "collapsed": false,
1087 "input": [
1244 "input": [
1088 "def is_int(number):\n",
1245 "def is_int(number):\n",
1089 " return int(number) == number\n",
1246 " return int(number) == number\n",
1090 "\n",
1247 "\n",
1091 "def factor_int(number):\n",
1248 "def factor_int(number):\n",
1092 " return [i + 1 for i in range(number) if is_int(number / (float(i) + 1.0))] "
1249 " return [i + 1 for i in range(number) if is_int(number / (float(i) + 1.0))] "
1093 ],
1250 ],
1094 "language": "python",
1251 "language": "python",
1095 "metadata": {},
1252 "metadata": {},
1096 "outputs": [],
1253 "outputs": [],
1097 "prompt_number": 13
1254 "prompt_number": 13
1098 },
1255 },
1099 {
1256 {
1100 "cell_type": "code",
1257 "cell_type": "code",
1101 "collapsed": false,
1258 "collapsed": false,
1102 "input": [
1259 "input": [
1103 "import time\n",
1260 "import time\n",
1104 "BACKGROUND = '#F7EBD5'\n",
1261 "BACKGROUND = '#F7EBD5'\n",
1105 "PARENT_COLOR = '#66635D'\n",
1262 "PARENT_COLOR = '#66635D'\n",
1106 "FACTOR_COLOR = '#6CC5C1'\n",
1263 "FACTOR_COLOR = '#6CC5C1'\n",
1107 "EDGE_COLOR = '#000000'\n",
1264 "EDGE_COLOR = '#000000'\n",
1108 "PRIME_COLOR = '#E54140'\n",
1265 "PRIME_COLOR = '#E54140'\n",
1109 "\n",
1266 "\n",
1110 "existing_graphs = []\n",
1267 "existing_graphs = []\n",
1111 "\n",
1268 "\n",
1112 "def add_unique_node(graph, value, **kwargs):\n",
1269 "def add_unique_node(graph, value, **kwargs):\n",
1113 " index = len(graph.node)\n",
1270 " index = len(graph.node)\n",
1114 " graph.add_node(index, charge=-50, strokewidth=0, value=value, **kwargs)\n",
1271 " graph.add_node(index, charge=-50, strokewidth=0, value=value, **kwargs)\n",
1115 " return index\n",
1272 " return index\n",
1116 "\n",
1273 "\n",
1117 "def plot_primes(graph, number, parent, start_number, delay=0.0):\n",
1274 "def plot_primes(graph, number, parent, start_number, delay=0.0):\n",
1118 " if delay > 0.0:\n",
1275 " if delay > 0.0:\n",
1119 " time.sleep(delay)\n",
1276 " time.sleep(delay)\n",
1120 " \n",
1277 " \n",
1121 " factors = factor_int(number)\n",
1278 " factors = factor_int(number)\n",
1122 " if len(factors) > 2:\n",
1279 " if len(factors) > 2:\n",
1123 " for factor in factors:\n",
1280 " for factor in factors:\n",
1124 " if factor != number:\n",
1281 " if factor != number:\n",
1125 " factor_size = max(float(factor) / start_number * 30.0,3.0)\n",
1282 " factor_size = max(float(factor) / start_number * 30.0,3.0)\n",
1126 " parent_factor_size = max(float(number) / start_number * 30.0,3.0)\n",
1283 " parent_factor_size = max(float(number) / start_number * 30.0,3.0)\n",
1127 " index = add_unique_node(graph, number, fill=FACTOR_COLOR, r='%.2fpx' % factor_size)\n",
1284 " index = add_unique_node(graph, number, fill=FACTOR_COLOR, r='%.2fpx' % factor_size)\n",
1128 " graph.add_edge(index, parent, distance=parent_factor_size+factor_size, stroke=EDGE_COLOR)\n",
1285 " graph.add_edge(index, parent, distance=parent_factor_size+factor_size, stroke=EDGE_COLOR)\n",
1129 " plot_primes(graph, factor, parent=index, start_number=start_number, delay=delay)\n",
1286 " plot_primes(graph, factor, parent=index, start_number=start_number, delay=delay)\n",
1130 " else:\n",
1287 " else:\n",
1131 " # Prime, set parent color to prime color.\n",
1288 " # Prime, set parent color to prime color.\n",
1132 " graph.node[parent]['fill'] = PRIME_COLOR\n",
1289 " graph.node[parent]['fill'] = PRIME_COLOR\n",
1133 "\n",
1290 "\n",
1134 "def graph_primes(number, delay):\n",
1291 "def graph_primes(number, delay):\n",
1135 " if len(existing_graphs) > 0:\n",
1292 " if len(existing_graphs) > 0:\n",
1136 " for graph in existing_graphs:\n",
1293 " for graph in existing_graphs:\n",
1137 " graph.close()\n",
1294 " graph.close()\n",
1138 " del existing_graphs[:]\n",
1295 " del existing_graphs[:]\n",
1139 " \n",
1296 " \n",
1140 " floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
1297 " floating_container = widgets.ContainerWidget(default_view_name='ModalView')\n",
1141 " floating_container.description = \"Factors of %d\" % number\n",
1298 " floating_container.description = \"Factors of %d\" % number\n",
1142 " floating_container.button_text = str(number)\n",
1299 " floating_container.button_text = str(number)\n",
1143 " floating_container.set_css({\n",
1300 " floating_container.set_css({\n",
1144 " 'width': '620px',\n",
1301 " 'width': '620px',\n",
1145 " 'height': '450px'}, selector='modal')\n",
1302 " 'height': '450px'}, selector='modal')\n",
1146 " \n",
1303 " \n",
1147 " graph = EventfulGraph()\n",
1304 " graph = EventfulGraph()\n",
1148 " d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1305 " d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1149 " floating_container.set_css('background', BACKGROUND)\n",
1306 " floating_container.set_css('background', BACKGROUND)\n",
1150 " d3.width = 600\n",
1307 " d3.width = 600\n",
1151 " d3.height = 400\n",
1308 " d3.height = 400\n",
1152 " display(floating_container)\n",
1309 " display(floating_container)\n",
1153 " existing_graphs.append(floating_container)\n",
1310 " existing_graphs.append(floating_container)\n",
1154 " \n",
1311 " \n",
1155 " index = add_unique_node(graph, number, fill=PARENT_COLOR, r='30px')\n",
1312 " index = add_unique_node(graph, number, fill=PARENT_COLOR, r='30px')\n",
1156 " plot_primes(graph, number=number, parent=index, start_number=number, delay=delay)"
1313 " plot_primes(graph, number=number, parent=index, start_number=number, delay=delay)"
1157 ],
1314 ],
1158 "language": "python",
1315 "language": "python",
1159 "metadata": {},
1316 "metadata": {},
1160 "outputs": [],
1317 "outputs": [],
1161 "prompt_number": 14
1318 "prompt_number": 14
1162 },
1319 },
1163 {
1320 {
1164 "cell_type": "code",
1321 "cell_type": "code",
1165 "collapsed": false,
1322 "collapsed": false,
1166 "input": [
1323 "input": [
1167 "box = widgets.ContainerWidget()\n",
1324 "box = widgets.ContainerWidget()\n",
1168 "box.vbox()\n",
1325 "box.vbox()\n",
1169 "box.align_center()\n",
1326 "box.align_center()\n",
1170 "box.pack_center()\n",
1327 "box.pack_center()\n",
1171 "header = widgets.StringWidget(parent=box, default_view_name=\"LabelView\", value=\"<h1>Number Factorizer</h1><br>\")\n",
1328 "header = widgets.StringWidget(parent=box, default_view_name=\"LabelView\", value=\"<h1>Number Factorizer</h1><br>\")\n",
1172 "subbox = widgets.ContainerWidget(parent=box)\n",
1329 "subbox = widgets.ContainerWidget(parent=box)\n",
1173 "subbox.hbox()\n",
1330 "subbox.hbox()\n",
1174 "subbox.align_center()\n",
1331 "subbox.align_center()\n",
1175 "subbox.pack_center()\n",
1332 "subbox.pack_center()\n",
1176 "number = widgets.IntWidget(value=100, parent=subbox)\n",
1333 "number = widgets.IntWidget(value=100, parent=subbox)\n",
1177 "button = widgets.ButtonWidget(description=\"Calculate\", parent=subbox)\n",
1334 "button = widgets.ButtonWidget(description=\"Calculate\", parent=subbox)\n",
1178 "speed = widgets.FloatRangeWidget(parent=box, min=0.0, max=0.5, value=0.4, step=0.01)\n",
1335 "speed = widgets.FloatRangeWidget(parent=box, min=0.0, max=0.5, value=0.4, step=0.01)\n",
1179 "display(box)\n",
1336 "display(box)\n",
1180 "box.add_class('well well-small')\n",
1337 "box.add_class('well well-small')\n",
1181 "\n",
1338 "\n",
1182 "def handle_caclulate():\n",
1339 "def handle_caclulate():\n",
1183 " graph_primes(number.value, 0.5-speed.value)\n",
1340 " graph_primes(number.value, 0.5-speed.value)\n",
1184 "button.on_click(handle_caclulate)\n"
1341 "button.on_click(handle_caclulate)\n"
1185 ],
1342 ],
1186 "language": "python",
1343 "language": "python",
1187 "metadata": {},
1344 "metadata": {},
1188 "outputs": [],
1345 "outputs": [
1346 {
1347 "ename": "TypeError",
1348 "evalue": "isinstance() arg 2 must be a class, type, or tuple of classes and types",
1349 "output_type": "pyerr",
1350 "traceback": [
1351 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
1352 "\u001b[0;32m<ipython-input-15-140cce028c66>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0mspeed\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwidgets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFloatRangeWidget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbox\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.4\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstep\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.01\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbox\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0mbox\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'well well-small'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mhandle_caclulate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1353 "\u001b[0;32m/Users/grout/projects/ipython-upstream/IPython/html/widgets/widget.pyc\u001b[0m in \u001b[0;36madd_class\u001b[0;34m(self, class_names, selector)\u001b[0m\n\u001b[1;32m 392\u001b[0m \"\"\"\n\u001b[1;32m 393\u001b[0m \u001b[0mclass_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mclass_names\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 394\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mclass_list\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 395\u001b[0m \u001b[0mclass_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m' '\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mclass_list\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 396\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
1354 "\u001b[0;31mTypeError\u001b[0m: isinstance() arg 2 must be a class, type, or tuple of classes and types"
1355 ]
1356 }
1357 ],
1189 "prompt_number": 15
1358 "prompt_number": 15
1190 },
1359 },
1191 {
1360 {
1192 "cell_type": "heading",
1361 "cell_type": "heading",
1193 "level": 2,
1362 "level": 2,
1194 "metadata": {},
1363 "metadata": {},
1195 "source": [
1364 "source": [
1196 "Twitter Tweet Watcher"
1365 "Twitter Tweet Watcher"
1197 ]
1366 ]
1198 },
1367 },
1199 {
1368 {
1200 "cell_type": "markdown",
1369 "cell_type": "markdown",
1201 "metadata": {},
1370 "metadata": {},
1202 "source": [
1371 "source": [
1203 "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."
1372 "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."
1204 ]
1373 ]
1205 },
1374 },
1206 {
1375 {
1207 "cell_type": "code",
1376 "cell_type": "code",
1208 "collapsed": false,
1377 "collapsed": false,
1209 "input": [
1378 "input": [
1210 "from twitter import *\n",
1379 "from twitter import *\n",
1211 "import time, datetime\n",
1380 "import time, datetime\n",
1212 "import math\n",
1381 "import math\n",
1213 "\n",
1382 "\n",
1214 "twitter_timestamp_format = \"%a %b %d %X +0000 %Y\""
1383 "twitter_timestamp_format = \"%a %b %d %X +0000 %Y\""
1215 ],
1384 ],
1216 "language": "python",
1385 "language": "python",
1217 "metadata": {},
1386 "metadata": {},
1218 "outputs": [],
1387 "outputs": [
1388 {
1389 "ename": "ImportError",
1390 "evalue": "No module named twitter",
1391 "output_type": "pyerr",
1392 "traceback": [
1393 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)",
1394 "\u001b[0;32m<ipython-input-16-2573b52a5cbe>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mtwitter\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mtwitter_timestamp_format\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"%a %b %d %X +0000 %Y\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1395 "\u001b[0;31mImportError\u001b[0m: No module named twitter"
1396 ]
1397 }
1398 ],
1219 "prompt_number": 16
1399 "prompt_number": 16
1220 },
1400 },
1221 {
1401 {
1222 "cell_type": "code",
1402 "cell_type": "code",
1223 "collapsed": false,
1403 "collapsed": false,
1224 "input": [
1404 "input": [
1225 "# Sign on to twitter.\n",
1405 "# Sign on to twitter.\n",
1226 "auth = OAuth(\n",
1406 "auth = OAuth(\n",
1227 " consumer_key='iQvYfTfuD86fgVWGjPY0UA',\n",
1407 " consumer_key='iQvYfTfuD86fgVWGjPY0UA',\n",
1228 " consumer_secret='C3jjP6vzYzTYoHV4s5NYPGuRkpT5SulKRKTkRmYg',\n",
1408 " consumer_secret='C3jjP6vzYzTYoHV4s5NYPGuRkpT5SulKRKTkRmYg',\n",
1229 " token='2218195843-cOPQa0D1Yk3JbvjvsCa0tIYzBOEWxINekmGcEql',\n",
1409 " token='2218195843-cOPQa0D1Yk3JbvjvsCa0tIYzBOEWxINekmGcEql',\n",
1230 " token_secret='3BFncT1zAvJRN6rj8haCxveZVLZWZ23QeulxzByXWlfoO'\n",
1410 " token_secret='3BFncT1zAvJRN6rj8haCxveZVLZWZ23QeulxzByXWlfoO'\n",
1231 ")\n",
1411 ")\n",
1232 "twitter = Twitter(auth = auth)\n",
1412 "twitter = Twitter(auth = auth)\n",
1233 "twitter_stream = TwitterStream(auth = auth, block = False)"
1413 "twitter_stream = TwitterStream(auth = auth, block = False)"
1234 ],
1414 ],
1235 "language": "python",
1415 "language": "python",
1236 "metadata": {},
1416 "metadata": {},
1237 "outputs": [],
1417 "outputs": [
1418 {
1419 "ename": "NameError",
1420 "evalue": "name 'OAuth' is not defined",
1421 "output_type": "pyerr",
1422 "traceback": [
1423 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
1424 "\u001b[0;32m<ipython-input-17-404c6c972436>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Sign on to twitter.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m auth = OAuth(\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mconsumer_key\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'iQvYfTfuD86fgVWGjPY0UA'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mconsumer_secret\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'C3jjP6vzYzTYoHV4s5NYPGuRkpT5SulKRKTkRmYg'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mtoken\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'2218195843-cOPQa0D1Yk3JbvjvsCa0tIYzBOEWxINekmGcEql'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1425 "\u001b[0;31mNameError\u001b[0m: name 'OAuth' is not defined"
1426 ]
1427 }
1428 ],
1238 "prompt_number": 17
1429 "prompt_number": 17
1239 },
1430 },
1240 {
1431 {
1241 "cell_type": "code",
1432 "cell_type": "code",
1242 "collapsed": false,
1433 "collapsed": false,
1243 "input": [
1434 "input": [
1244 "widget_container = widgets.ContainerWidget()\n",
1435 "widget_container = widgets.ContainerWidget()\n",
1245 "widget_container.hbox()\n",
1436 "widget_container.hbox()\n",
1246 "floating_container = widgets.ContainerWidget(parent=widget_container, default_view_name='ModalView')\n",
1437 "floating_container = widgets.ContainerWidget(parent=widget_container, default_view_name='ModalView')\n",
1247 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
1438 "floating_container.description = \"Dynamic D3 rendering of a NetworkX graph\"\n",
1248 "floating_container.button_text = \"Render Window\"\n",
1439 "floating_container.button_text = \"Render Window\"\n",
1249 "floating_container.set_css({\n",
1440 "floating_container.set_css({\n",
1250 " 'width': '620px',\n",
1441 " 'width': '620px',\n",
1251 " 'height': '450px'}, selector='modal')\n",
1442 " 'height': '450px'}, selector='modal')\n",
1252 "\n",
1443 "\n",
1253 "graph = EventfulGraph()\n",
1444 "graph = EventfulGraph()\n",
1254 "d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1445 "d3 = ForceDirectedGraphWidget(graph, parent=floating_container)\n",
1255 "d3.width = 600\n",
1446 "d3.width = 600\n",
1256 "d3.height = 400\n",
1447 "d3.height = 400\n",
1257 "\n",
1448 "\n",
1258 "stop_button = widgets.ButtonWidget(parent=widget_container, description=\"Stop\")\n",
1449 "stop_button = widgets.ButtonWidget(parent=widget_container, description=\"Stop\")\n",
1259 "stop_button.set_css('margin-left', '5px')\n",
1450 "stop_button.set_css('margin-left', '5px')\n",
1260 " \n",
1451 " \n",
1261 "# Only listen to tweets while they are available and the user\n",
1452 "# Only listen to tweets while they are available and the user\n",
1262 "# doesn't want to stop.\n",
1453 "# doesn't want to stop.\n",
1263 "stop_listening = [False]\n",
1454 "stop_listening = [False]\n",
1264 "def handle_stop():\n",
1455 "def handle_stop():\n",
1265 " stop_listening[0] = True\n",
1456 " stop_listening[0] = True\n",
1266 " print(\"Service stopped\")\n",
1457 " print(\"Service stopped\")\n",
1267 "stop_button.on_click(handle_stop)\n",
1458 "stop_button.on_click(handle_stop)\n",
1268 "\n",
1459 "\n",
1269 "def watch_tweets(screen_name=None):\n",
1460 "def watch_tweets(screen_name=None):\n",
1270 " display(widget_container)\n",
1461 " display(widget_container)\n",
1271 " graph.node.clear()\n",
1462 " graph.node.clear()\n",
1272 " graph.adj.clear()\n",
1463 " graph.adj.clear()\n",
1273 " start_timestamp = None\n",
1464 " start_timestamp = None\n",
1274 " stop_button.add_class('btn-danger')\n",
1465 " stop_button.add_class('btn-danger')\n",
1275 " \n",
1466 " \n",
1276 " # Get Barack's tweets\n",
1467 " # Get Barack's tweets\n",
1277 " tweets = twitter.statuses.user_timeline(screen_name=screen_name)\n",
1468 " tweets = twitter.statuses.user_timeline(screen_name=screen_name)\n",
1278 " user_id = twitter.users.lookup(screen_name=screen_name)[0]['id']\n",
1469 " user_id = twitter.users.lookup(screen_name=screen_name)[0]['id']\n",
1279 " \n",
1470 " \n",
1280 " # Determine the maximum number of retweets.\n",
1471 " # Determine the maximum number of retweets.\n",
1281 " max_retweets = 0.0\n",
1472 " max_retweets = 0.0\n",
1282 " for tweet in tweets:\n",
1473 " for tweet in tweets:\n",
1283 " max_retweets = float(max(tweet['retweet_count'], max_retweets))\n",
1474 " max_retweets = float(max(tweet['retweet_count'], max_retweets))\n",
1284 " \n",
1475 " \n",
1285 " \n",
1476 " \n",
1286 " def plot_tweet(tweet, parent=None, elapsed_seconds=1.0, color=\"gold\"):\n",
1477 " def plot_tweet(tweet, parent=None, elapsed_seconds=1.0, color=\"gold\"):\n",
1287 " new_id = tweet['id']\n",
1478 " new_id = tweet['id']\n",
1288 " graph.add_node(\n",
1479 " graph.add_node(\n",
1289 " new_id, \n",
1480 " new_id, \n",
1290 " r=max(float(tweet['retweet_count']) / max_retweets * 30.0, 3.0),\n",
1481 " r=max(float(tweet['retweet_count']) / max_retweets * 30.0, 3.0),\n",
1291 " charge=-60,\n",
1482 " charge=-60,\n",
1292 " fill = color,\n",
1483 " fill = color,\n",
1293 " )\n",
1484 " )\n",
1294 " \n",
1485 " \n",
1295 " if parent is not None:\n",
1486 " if parent is not None:\n",
1296 " parent_radius = max(float(parent['retweet_count']) / max_retweets * 30.0, 3.0)\n",
1487 " parent_radius = max(float(parent['retweet_count']) / max_retweets * 30.0, 3.0)\n",
1297 " graph.node[parent['id']]['r'] = parent_radius\n",
1488 " graph.node[parent['id']]['r'] = parent_radius\n",
1298 " \n",
1489 " \n",
1299 " graph.add_edge(new_id, parent['id'], distance=math.log(elapsed_seconds) * 9.0 + parent_radius)\n",
1490 " graph.add_edge(new_id, parent['id'], distance=math.log(elapsed_seconds) * 9.0 + parent_radius)\n",
1300 " graph.node[new_id]['fill'] = 'red'\n",
1491 " graph.node[new_id]['fill'] = 'red'\n",
1301 " \n",
1492 " \n",
1302 " \n",
1493 " \n",
1303 " # Plot each tweet.\n",
1494 " # Plot each tweet.\n",
1304 " for tweet in tweets:\n",
1495 " for tweet in tweets:\n",
1305 " plot_tweet(tweet)\n",
1496 " plot_tweet(tweet)\n",
1306 " \n",
1497 " \n",
1307 " kernel=get_ipython().kernel\n",
1498 " kernel=get_ipython().kernel\n",
1308 " iterator = twitter_stream.statuses.filter(follow=user_id)\n",
1499 " iterator = twitter_stream.statuses.filter(follow=user_id)\n",
1309 " \n",
1500 " \n",
1310 " while not stop_listening[0]:\n",
1501 " while not stop_listening[0]:\n",
1311 " kernel.do_one_iteration()\n",
1502 " kernel.do_one_iteration()\n",
1312 " \n",
1503 " \n",
1313 " for tweet in iterator:\n",
1504 " for tweet in iterator:\n",
1314 " kernel.do_one_iteration()\n",
1505 " kernel.do_one_iteration()\n",
1315 " if stop_listening[0] or tweet is None:\n",
1506 " if stop_listening[0] or tweet is None:\n",
1316 " break\n",
1507 " break\n",
1317 " else:\n",
1508 " else:\n",
1318 " if 'retweeted_status' in tweet:\n",
1509 " if 'retweeted_status' in tweet:\n",
1319 " original_tweet = tweet['retweeted_status']\n",
1510 " original_tweet = tweet['retweeted_status']\n",
1320 " if original_tweet['id'] in graph.node:\n",
1511 " if original_tweet['id'] in graph.node:\n",
1321 " tweet_timestamp = datetime.datetime.strptime(tweet['created_at'], twitter_timestamp_format) \n",
1512 " tweet_timestamp = datetime.datetime.strptime(tweet['created_at'], twitter_timestamp_format) \n",
1322 " if start_timestamp is None:\n",
1513 " if start_timestamp is None:\n",
1323 " start_timestamp = tweet_timestamp\n",
1514 " start_timestamp = tweet_timestamp\n",
1324 " elapsed_seconds = max((tweet_timestamp - start_timestamp).total_seconds(),1.0)\n",
1515 " elapsed_seconds = max((tweet_timestamp - start_timestamp).total_seconds(),1.0)\n",
1325 " \n",
1516 " \n",
1326 " plot_tweet(tweet, parent=original_tweet, elapsed_seconds=elapsed_seconds)\n",
1517 " plot_tweet(tweet, parent=original_tweet, elapsed_seconds=elapsed_seconds)\n",
1327 " elif 'id' in tweet:\n",
1518 " elif 'id' in tweet:\n",
1328 " plot_tweet(tweet, color='lime')\n"
1519 " plot_tweet(tweet, color='lime')\n"
1329 ],
1520 ],
1330 "language": "python",
1521 "language": "python",
1331 "metadata": {},
1522 "metadata": {},
1332 "outputs": [],
1523 "outputs": [
1524 {
1525 "ename": "KeyError",
1526 "evalue": "'modal'",
1527 "output_type": "pyerr",
1528 "traceback": [
1529 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
1530 "\u001b[0;32m<ipython-input-18-51ebdd7c9d2e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 6\u001b[0m floating_container.set_css({\n\u001b[1;32m 7\u001b[0m \u001b[0;34m'width'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m'620px'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m 'height': '450px'}, selector='modal')\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mgraph\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mEventfulGraph\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1531 "\u001b[0;32m/Users/grout/projects/ipython-upstream/IPython/html/widgets/widget.pyc\u001b[0m in \u001b[0;36mset_css\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 355\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 356\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 357\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_css\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mselector\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_css\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mselector\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 358\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_css\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mselector\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 359\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend_state\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'_css'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
1532 "\u001b[0;31mKeyError\u001b[0m: 'modal'"
1533 ]
1534 }
1535 ],
1333 "prompt_number": 18
1536 "prompt_number": 18
1334 },
1537 },
1335 {
1538 {
1336 "cell_type": "code",
1539 "cell_type": "code",
1337 "collapsed": false,
1540 "collapsed": false,
1338 "input": [
1541 "input": [
1339 "watch_tweets(screen_name=\"justinbieber\")"
1542 "watch_tweets(screen_name=\"justinbieber\")"
1340 ],
1543 ],
1341 "language": "python",
1544 "language": "python",
1342 "metadata": {},
1545 "metadata": {},
1343 "outputs": [
1546 "outputs": [
1344 {
1547 {
1345 "output_type": "stream",
1548 "ename": "NameError",
1346 "stream": "stdout",
1549 "evalue": "name 'watch_tweets' is not defined",
1347 "text": [
1550 "output_type": "pyerr",
1348 "Service stopped\n"
1551 "traceback": [
1552 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
1553 "\u001b[0;32m<ipython-input-19-f7b582ac8226>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mwatch_tweets\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mscreen_name\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"justinbieber\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
1554 "\u001b[0;31mNameError\u001b[0m: name 'watch_tweets' is not defined"
1349 ]
1555 ]
1350 }
1556 }
1351 ],
1557 ],
1352 "prompt_number": 19
1558 "prompt_number": 19
1559 },
1560 {
1561 "cell_type": "code",
1562 "collapsed": false,
1563 "input": [],
1564 "language": "python",
1565 "metadata": {},
1566 "outputs": [],
1567 "prompt_number": 19
1568 },
1569 {
1570 "cell_type": "code",
1571 "collapsed": false,
1572 "input": [],
1573 "language": "python",
1574 "metadata": {},
1575 "outputs": []
1353 }
1576 }
1354 ],
1577 ],
1355 "metadata": {}
1578 "metadata": {}
1356 }
1579 }
1357 ]
1580 ]
1358 } No newline at end of file
1581 }
@@ -1,368 +1,369 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "cell_tags": [
3 "cell_tags": [
4 [
4 [
5 "<None>",
5 "<None>",
6 null
6 null
7 ]
7 ]
8 ],
8 ],
9 "name": ""
9 "name": ""
10 },
10 },
11 "nbformat": 3,
11 "nbformat": 3,
12 "nbformat_minor": 0,
12 "nbformat_minor": 0,
13 "worksheets": [
13 "worksheets": [
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "markdown",
17 "cell_type": "markdown",
18 "metadata": {},
18 "metadata": {},
19 "source": [
19 "source": [
20 "To use IPython widgets in the notebook, the widget namespace and display function need to be imported."
20 "To use IPython widgets in the notebook, the widget namespace and display function need to be imported."
21 ]
21 ]
22 },
22 },
23 {
23 {
24 "cell_type": "code",
24 "cell_type": "code",
25 "collapsed": false,
25 "collapsed": false,
26 "input": [
26 "input": [
27 "from IPython.html import widgets # Widget definitions\n",
27 "from IPython.html import widgets # Widget definitions\n",
28 "from IPython.display import display # Used to display widgets in the notebook"
28 "from IPython.display import display # Used to display widgets in the notebook"
29 ],
29 ],
30 "language": "python",
30 "language": "python",
31 "metadata": {},
31 "metadata": {},
32 "outputs": [],
32 "outputs": [],
33 "prompt_number": 1
33 "prompt_number": 1
34 },
34 },
35 {
35 {
36 "cell_type": "heading",
36 "cell_type": "heading",
37 "level": 1,
37 "level": 1,
38 "metadata": {},
38 "metadata": {},
39 "source": [
39 "source": [
40 "Basic Widgets"
40 "Basic Widgets"
41 ]
41 ]
42 },
42 },
43 {
43 {
44 "cell_type": "markdown",
44 "cell_type": "markdown",
45 "metadata": {},
45 "metadata": {},
46 "source": [
46 "source": [
47 "The IPython notebook comes preloaded with basic widgets that represent common data types. These widgets are\n",
47 "The IPython notebook comes preloaded with basic widgets that represent common data types. These widgets are\n",
48 "\n",
48 "\n",
49 "- BoolWidget : boolean \n",
49 "- BoolWidget : boolean \n",
50 "- FloatRangeWidget : bounded float \n",
50 "- FloatRangeWidget : bounded float \n",
51 "- FloatWidget : unbounded float \n",
51 "- FloatWidget : unbounded float \n",
52 "- ImageWidget : image\n",
52 "- ImageWidget : image\n",
53 "- IntRangeWidget : bounded integer \n",
53 "- IntRangeWidget : bounded integer \n",
54 "- IntWidget : unbounded integer \n",
54 "- IntWidget : unbounded integer \n",
55 "- SelectionWidget : enumeration \n",
55 "- SelectionWidget : enumeration \n",
56 "- StringWidget : string \n",
56 "- StringWidget : string \n",
57 "\n",
57 "\n",
58 "A few special widgets are also included, that can be used to capture events and change how other widgets are displayed. These widgets are\n",
58 "A few special widgets are also included, that can be used to capture events and change how other widgets are displayed. These widgets are\n",
59 "\n",
59 "\n",
60 "- ButtonWidget \n",
60 "- ButtonWidget \n",
61 "- ContainerWidget \n",
61 "- ContainerWidget \n",
62 "- MulticontainerWidget \n",
62 "- MulticontainerWidget \n",
63 "\n",
63 "\n",
64 "To see the complete list of widgets, one can execute the following"
64 "To see the complete list of widgets, one can execute the following"
65 ]
65 ]
66 },
66 },
67 {
67 {
68 "cell_type": "code",
68 "cell_type": "code",
69 "collapsed": false,
69 "collapsed": false,
70 "input": [
70 "input": [
71 "[widget for widget in dir(widgets) if widget.endswith('Widget')]"
71 "[widget for widget in dir(widgets) if widget.endswith('Widget')]"
72 ],
72 ],
73 "language": "python",
73 "language": "python",
74 "metadata": {},
74 "metadata": {},
75 "outputs": [
75 "outputs": [
76 {
76 {
77 "metadata": {},
77 "metadata": {},
78 "output_type": "pyout",
78 "output_type": "pyout",
79 "prompt_number": 2,
79 "prompt_number": 2,
80 "text": [
80 "text": [
81 "['BoolWidget',\n",
81 "['BoolWidget',\n",
82 " 'ButtonWidget',\n",
82 " 'ButtonWidget',\n",
83 " 'ContainerWidget',\n",
83 " 'ContainerWidget',\n",
84 " 'DOMWidget',\n",
84 " 'FloatRangeWidget',\n",
85 " 'FloatRangeWidget',\n",
85 " 'FloatWidget',\n",
86 " 'FloatWidget',\n",
86 " 'ImageWidget',\n",
87 " 'ImageWidget',\n",
87 " 'IntRangeWidget',\n",
88 " 'IntRangeWidget',\n",
88 " 'IntWidget',\n",
89 " 'IntWidget',\n",
89 " 'MulticontainerWidget',\n",
90 " 'SelectionContainerWidget',\n",
90 " 'SelectionWidget',\n",
91 " 'SelectionWidget',\n",
91 " 'StringWidget',\n",
92 " 'StringWidget',\n",
92 " 'Widget']"
93 " 'Widget']"
93 ]
94 ]
94 }
95 }
95 ],
96 ],
96 "prompt_number": 2
97 "prompt_number": 2
97 },
98 },
98 {
99 {
99 "cell_type": "markdown",
100 "cell_type": "markdown",
100 "metadata": {},
101 "metadata": {},
101 "source": [
102 "source": [
102 "The basic widgets can all be constructed without arguments. The following creates a FloatRangeWidget without displaying it"
103 "The basic widgets can all be constructed without arguments. The following creates a FloatRangeWidget without displaying it"
103 ]
104 ]
104 },
105 },
105 {
106 {
106 "cell_type": "code",
107 "cell_type": "code",
107 "collapsed": false,
108 "collapsed": false,
108 "input": [
109 "input": [
109 "mywidget = widgets.FloatRangeWidget()"
110 "mywidget = widgets.FloatRangeWidget()"
110 ],
111 ],
111 "language": "python",
112 "language": "python",
112 "metadata": {},
113 "metadata": {},
113 "outputs": [],
114 "outputs": [],
114 "prompt_number": 3
115 "prompt_number": 3
115 },
116 },
116 {
117 {
117 "cell_type": "markdown",
118 "cell_type": "markdown",
118 "metadata": {},
119 "metadata": {},
119 "source": [
120 "source": [
120 "Constructing a widget does not display it on the page. To display a widget, the widget must be passed to the IPython `display(object)` method. `mywidget` is displayed by"
121 "Constructing a widget does not display it on the page. To display a widget, the widget must be passed to the IPython `display(object)` method. `mywidget` is displayed by"
121 ]
122 ]
122 },
123 },
123 {
124 {
124 "cell_type": "code",
125 "cell_type": "code",
125 "collapsed": false,
126 "collapsed": false,
126 "input": [
127 "input": [
127 "display(mywidget)"
128 "display(mywidget)"
128 ],
129 ],
129 "language": "python",
130 "language": "python",
130 "metadata": {},
131 "metadata": {},
131 "outputs": [],
132 "outputs": [],
132 "prompt_number": 4
133 "prompt_number": 4
133 },
134 },
134 {
135 {
135 "cell_type": "code",
136 "cell_type": "code",
136 "collapsed": false,
137 "collapsed": false,
137 "input": [
138 "input": [
138 "mywidget.value\n"
139 "mywidget.value\n"
139 ],
140 ],
140 "language": "python",
141 "language": "python",
141 "metadata": {},
142 "metadata": {},
142 "outputs": [
143 "outputs": [
143 {
144 {
144 "metadata": {},
145 "metadata": {},
145 "output_type": "pyout",
146 "output_type": "pyout",
146 "prompt_number": 13,
147 "prompt_number": 10,
147 "text": [
148 "text": [
148 "42.7"
149 "50.6"
149 ]
150 ]
150 }
151 }
151 ],
152 ],
152 "prompt_number": 13
153 "prompt_number": 10
153 },
154 },
154 {
155 {
155 "cell_type": "markdown",
156 "cell_type": "markdown",
156 "metadata": {},
157 "metadata": {},
157 "source": [
158 "source": [
158 "It's important to realize that widgets are not the same as output, even though they are displayed with `display`. Widgets are drawn in a special widget area. That area is marked with a close button which allows you to collapse the widgets. Widgets cannot be interleaved with output. Doing so would break the ability to make simple animations using `clear_output`.\n",
159 "It's important to realize that widgets are not the same as output, even though they are displayed with `display`. Widgets are drawn in a special widget area. That area is marked with a close button which allows you to collapse the widgets. Widgets cannot be interleaved with output. Doing so would break the ability to make simple animations using `clear_output`.\n",
159 "\n",
160 "\n",
160 "Widgets are manipulated via special instance properties (traitlets). The names of these instance properties are listed in the widget's `keys` property (as seen below). A few of these properties are common to most, if not all, widgets. The common properties are `value`, `description`, `visible`, and `disabled`. `_css`, `_add_class`, and `_remove_class` are internal properties that exist in all widgets and should not be modified."
161 "Widgets are manipulated via special instance properties (traitlets). The names of these instance properties are listed in the widget's `keys` property (as seen below). A few of these properties are common to most, if not all, widgets. The common properties are `value`, `description`, `visible`, and `disabled`. `_css`, `_add_class`, and `_remove_class` are internal properties that exist in all widgets and should not be modified."
161 ]
162 ]
162 },
163 },
163 {
164 {
164 "cell_type": "code",
165 "cell_type": "code",
165 "collapsed": false,
166 "collapsed": false,
166 "input": [
167 "input": [
167 "mywidget.keys"
168 "mywidget.keys"
168 ],
169 ],
169 "language": "python",
170 "language": "python",
170 "metadata": {},
171 "metadata": {},
171 "outputs": [
172 "outputs": [
172 {
173 {
173 "metadata": {},
174 "metadata": {},
174 "output_type": "pyout",
175 "output_type": "pyout",
175 "prompt_number": 14,
176 "prompt_number": 11,
176 "text": [
177 "text": [
177 "['visible',\n",
178 "['value',\n",
178 " '_css',\n",
179 " 'default_view_name',\n",
180 " 'value',\n",
181 " 'step',\n",
179 " 'step',\n",
182 " 'max',\n",
180 " 'max',\n",
183 " 'min',\n",
181 " 'min',\n",
184 " 'disabled',\n",
182 " 'disabled',\n",
185 " 'orientation',\n",
183 " 'orientation',\n",
186 " 'description']"
184 " 'description',\n",
185 " 'visible',\n",
186 " '_css',\n",
187 " 'view_name']"
187 ]
188 ]
188 }
189 }
189 ],
190 ],
190 "prompt_number": 14
191 "prompt_number": 11
191 },
192 },
192 {
193 {
193 "cell_type": "markdown",
194 "cell_type": "markdown",
194 "metadata": {},
195 "metadata": {},
195 "source": [
196 "source": [
196 "Changing a widget's property value will automatically update that widget everywhere it is displayed in the notebook. Here the value of `mywidget` is set. The slider shown above (after input 4) updates automatically to the new value. In reverse, changing the value of the displayed widget will update the property's value."
197 "Changing a widget's property value will automatically update that widget everywhere it is displayed in the notebook. Here the value of `mywidget` is set. The slider shown above (after input 4) updates automatically to the new value. In reverse, changing the value of the displayed widget will update the property's value."
197 ]
198 ]
198 },
199 },
199 {
200 {
200 "cell_type": "code",
201 "cell_type": "code",
201 "collapsed": false,
202 "collapsed": false,
202 "input": [
203 "input": [
203 "mywidget.value = 25.0"
204 "mywidget.value = 25.0"
204 ],
205 ],
205 "language": "python",
206 "language": "python",
206 "metadata": {},
207 "metadata": {},
207 "outputs": [],
208 "outputs": [],
208 "prompt_number": 15
209 "prompt_number": 12
209 },
210 },
210 {
211 {
211 "cell_type": "markdown",
212 "cell_type": "markdown",
212 "metadata": {},
213 "metadata": {},
213 "source": [
214 "source": [
214 "After changing the widget's value in the notebook by hand to 0.0 (sliding the bar to the far left)."
215 "After changing the widget's value in the notebook by hand to 0.0 (sliding the bar to the far left)."
215 ]
216 ]
216 },
217 },
217 {
218 {
218 "cell_type": "code",
219 "cell_type": "code",
219 "collapsed": false,
220 "collapsed": false,
220 "input": [
221 "input": [
221 "mywidget.value"
222 "mywidget.value"
222 ],
223 ],
223 "language": "python",
224 "language": "python",
224 "metadata": {},
225 "metadata": {},
225 "outputs": [
226 "outputs": [
226 {
227 {
227 "metadata": {},
228 "metadata": {},
228 "output_type": "pyout",
229 "output_type": "pyout",
229 "prompt_number": 16,
230 "prompt_number": 13,
230 "text": [
231 "text": [
231 "25.0"
232 "25.0"
232 ]
233 ]
233 }
234 }
234 ],
235 ],
235 "prompt_number": 16
236 "prompt_number": 13
236 },
237 },
237 {
238 {
238 "cell_type": "markdown",
239 "cell_type": "markdown",
239 "metadata": {},
240 "metadata": {},
240 "source": [
241 "source": [
241 "Widget property values can also be set with kwargs during the construction of the widget (as seen below)."
242 "Widget property values can also be set with kwargs during the construction of the widget (as seen below)."
242 ]
243 ]
243 },
244 },
244 {
245 {
245 "cell_type": "code",
246 "cell_type": "code",
246 "collapsed": false,
247 "collapsed": false,
247 "input": [
248 "input": [
248 "mysecondwidget = widgets.SelectionWidget(values=[\"Item A\", \"Item B\", \"Item C\"], value=\"Nothing Selected\")\n",
249 "mysecondwidget = widgets.SelectionWidget(values=[\"Item A\", \"Item B\", \"Item C\"], value=\"Nothing Selected\")\n",
249 "display(mysecondwidget)"
250 "display(mysecondwidget)"
250 ],
251 ],
251 "language": "python",
252 "language": "python",
252 "metadata": {},
253 "metadata": {},
253 "outputs": [],
254 "outputs": [],
254 "prompt_number": 17
255 "prompt_number": 14
255 },
256 },
256 {
257 {
257 "cell_type": "code",
258 "cell_type": "code",
258 "collapsed": false,
259 "collapsed": false,
259 "input": [
260 "input": [
260 "mysecondwidget.value"
261 "mysecondwidget.value"
261 ],
262 ],
262 "language": "python",
263 "language": "python",
263 "metadata": {},
264 "metadata": {},
264 "outputs": [
265 "outputs": [
265 {
266 {
266 "metadata": {},
267 "metadata": {},
267 "output_type": "pyout",
268 "output_type": "pyout",
268 "prompt_number": 18,
269 "prompt_number": 15,
269 "text": [
270 "text": [
270 "u'Nothing Selected'"
271 "u'Item B'"
271 ]
272 ]
272 }
273 }
273 ],
274 ],
274 "prompt_number": 18
275 "prompt_number": 15
275 },
276 },
276 {
277 {
277 "cell_type": "heading",
278 "cell_type": "heading",
278 "level": 1,
279 "level": 1,
279 "metadata": {},
280 "metadata": {},
280 "source": [
281 "source": [
281 "Views"
282 "Views"
282 ]
283 ]
283 },
284 },
284 {
285 {
285 "cell_type": "markdown",
286 "cell_type": "markdown",
286 "metadata": {},
287 "metadata": {},
287 "source": [
288 "source": [
288 "The data types that most of the widgets represent can be displayed more than one way. A `view` is a visual representation of a widget in the notebook. In the example in the section above, the default `view` for the `FloatRangeWidget` is used. The default view is set in the widgets `default_view_name` instance property (as seen below)."
289 "The data types that most of the widgets represent can be displayed more than one way. A `view` is a visual representation of a widget in the notebook. In the example in the section above, the default `view` for the `FloatRangeWidget` is used. The default view is set in the widgets `default_view_name` instance property (as seen below)."
289 ]
290 ]
290 },
291 },
291 {
292 {
292 "cell_type": "code",
293 "cell_type": "code",
293 "collapsed": false,
294 "collapsed": false,
294 "input": [
295 "input": [
295 "mywidget.default_view_name"
296 "mywidget.default_view_name"
296 ],
297 ],
297 "language": "python",
298 "language": "python",
298 "metadata": {},
299 "metadata": {},
299 "outputs": [
300 "outputs": [
300 {
301 {
301 "metadata": {},
302 "metadata": {},
302 "output_type": "pyout",
303 "output_type": "pyout",
303 "prompt_number": 19,
304 "prompt_number": 19,
304 "text": [
305 "text": [
305 "u'FloatSliderView'"
306 "u'FloatSliderView'"
306 ]
307 ]
307 }
308 }
308 ],
309 ],
309 "prompt_number": 19
310 "prompt_number": 19
310 },
311 },
311 {
312 {
312 "cell_type": "markdown",
313 "cell_type": "markdown",
313 "metadata": {},
314 "metadata": {},
314 "source": [
315 "source": [
315 "When a widget is displayed using `display(...)`, the `default_view_name` is used to determine what view type should be used to display the widget. View names are case sensitive. Sometimes the default view isn't the best view to represent a piece of data. To change what view is used, either the `default_view_name` can be changed or the `view_name` kwarg of `display` can be set. This also can be used to display one widget multiple ways in one output (as seen below)."
316 "When a widget is displayed using `display(...)`, the `default_view_name` is used to determine what view type should be used to display the widget. View names are case sensitive. Sometimes the default view isn't the best view to represent a piece of data. To change what view is used, either the `default_view_name` can be changed or the `view_name` kwarg of `display` can be set. This also can be used to display one widget multiple ways in one output (as seen below)."
316 ]
317 ]
317 },
318 },
318 {
319 {
319 "cell_type": "code",
320 "cell_type": "code",
320 "collapsed": false,
321 "collapsed": false,
321 "input": [
322 "input": [
322 "display(mywidget)\n",
323 "display(mywidget)\n",
323 "display(mywidget, view_name=\"FloatTextView\")"
324 "display(mywidget, view_name=\"FloatTextView\")"
324 ],
325 ],
325 "language": "python",
326 "language": "python",
326 "metadata": {},
327 "metadata": {},
327 "outputs": [],
328 "outputs": [],
328 "prompt_number": 20
329 "prompt_number": 20
329 },
330 },
330 {
331 {
331 "cell_type": "markdown",
332 "cell_type": "markdown",
332 "metadata": {},
333 "metadata": {},
333 "source": [
334 "source": [
334 "Some views work with multiple different widget types and some views only work with one. The complete list of views and supported widgets is below. The default views are italicized.\n",
335 "Some views work with multiple different widget types and some views only work with one. The complete list of views and supported widgets is below. The default views are italicized.\n",
335 "\n",
336 "\n",
336 "| Widget Name | View Names |\n",
337 "| Widget Name | View Names |\n",
337 "|:-----------------------|:--------------------|\n",
338 "|:-----------------------|:--------------------|\n",
338 "| BoolWidget | *CheckboxView* |\n",
339 "| BoolWidget | *CheckboxView* |\n",
339 "| | ToggleButtonView |\n",
340 "| | ToggleButtonView |\n",
340 "| ButtonWidget | *ButtonView* |\n",
341 "| ButtonWidget | *ButtonView* |\n",
341 "| ContainerWidget | *ContainerView* |\n",
342 "| ContainerWidget | *ContainerView* |\n",
342 "| | ModalView |\n",
343 "| | ModalView |\n",
343 "| FloatRangeWidget | *FloatSliderView* |\n",
344 "| FloatRangeWidget | *FloatSliderView* |\n",
344 "| | FloatTextView |\n",
345 "| | FloatTextView |\n",
345 "| | ProgressView |\n",
346 "| | ProgressView |\n",
346 "| FloatWidget | *FloatTextView* |\n",
347 "| FloatWidget | *FloatTextView* |\n",
347 "| ImageWidget | *ImageView* |\n",
348 "| ImageWidget | *ImageView* |\n",
348 "| IntRangeWidget | *IntSliderView* |\n",
349 "| IntRangeWidget | *IntSliderView* |\n",
349 "| | IntTextView |\n",
350 "| | IntTextView |\n",
350 "| | ProgressView |\n",
351 "| | ProgressView |\n",
351 "| IntWidget | *IntTextView* |\n",
352 "| IntWidget | *IntTextView* |\n",
352 "| MulticontainerWidget | AccordionView |\n",
353 "| MulticontainerWidget | AccordionView |\n",
353 "| | *TabView* |\n",
354 "| | *TabView* |\n",
354 "| SelectionWidget | ToggleButtonsView |\n",
355 "| SelectionWidget | ToggleButtonsView |\n",
355 "| | RadioButtonsView |\n",
356 "| | RadioButtonsView |\n",
356 "| | *DropdownView* |\n",
357 "| | *DropdownView* |\n",
357 "| | ListBoxView |\n",
358 "| | ListBoxView |\n",
358 "| StringWidget | HTMLView |\n",
359 "| StringWidget | HTMLView |\n",
359 "| | LatexView |\n",
360 "| | LatexView |\n",
360 "| | TextAreaView |\n",
361 "| | TextAreaView |\n",
361 "| | *TextBoxView* |\n"
362 "| | *TextBoxView* |\n"
362 ]
363 ]
363 }
364 }
364 ],
365 ],
365 "metadata": {}
366 "metadata": {}
366 }
367 }
367 ]
368 ]
368 } No newline at end of file
369 }
@@ -1,750 +1,662 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "cell_tags": [
3 "cell_tags": [
4 [
4 [
5 "<None>",
5 "<None>",
6 null
6 null
7 ]
7 ]
8 ],
8 ],
9 "name": ""
9 "name": ""
10 },
10 },
11 "nbformat": 3,
11 "nbformat": 3,
12 "nbformat_minor": 0,
12 "nbformat_minor": 0,
13 "worksheets": [
13 "worksheets": [
14 {
14 {
15 "cells": [
15 "cells": [
16 {
16 {
17 "cell_type": "code",
17 "cell_type": "code",
18 "collapsed": false,
18 "collapsed": false,
19 "input": [
19 "input": [
20 "from __future__ import print_function # 2.7 compatability\n",
20 "from __future__ import print_function # 2.7 compatability\n",
21 "\n",
21 "\n",
22 "from IPython.html import widgets # Widget definitions\n",
22 "from IPython.html import widgets # Widget definitions\n",
23 "from IPython.display import display # Used to display widgets in the notebook"
23 "from IPython.display import display # Used to display widgets in the notebook"
24 ],
24 ],
25 "language": "python",
25 "language": "python",
26 "metadata": {},
26 "metadata": {},
27 "outputs": [],
27 "outputs": [],
28 "prompt_number": 2
28 "prompt_number": 1
29 },
29 },
30 {
30 {
31 "cell_type": "heading",
31 "cell_type": "heading",
32 "level": 1,
32 "level": 1,
33 "metadata": {},
33 "metadata": {},
34 "source": [
34 "source": [
35 "Traitlet Events"
35 "Traitlet Events"
36 ]
36 ]
37 },
37 },
38 {
38 {
39 "cell_type": "markdown",
39 "cell_type": "markdown",
40 "metadata": {},
40 "metadata": {},
41 "source": [
41 "source": [
42 "The widget properties are IPython traitlets. Traitlets are eventful. To handle property value changes, the `on_trait_change` method of the widget can be used to register an event handling callback. The doc string for `on_trait_change` can be seen below. Both the `name` and `remove` properties are optional."
42 "The widget properties are IPython traitlets. Traitlets are eventful. To handle property value changes, the `on_trait_change` method of the widget can be used to register an event handling callback. The doc string for `on_trait_change` can be seen below. Both the `name` and `remove` properties are optional."
43 ]
43 ]
44 },
44 },
45 {
45 {
46 "cell_type": "code",
46 "cell_type": "code",
47 "collapsed": false,
47 "collapsed": false,
48 "input": [
48 "input": [
49 "print(widgets.Widget.on_trait_change.__doc__)"
49 "print(widgets.Widget.on_trait_change.__doc__)"
50 ],
50 ],
51 "language": "python",
51 "language": "python",
52 "metadata": {},
52 "metadata": {},
53 "outputs": [
53 "outputs": [
54 {
54 {
55 "output_type": "stream",
55 "output_type": "stream",
56 "stream": "stdout",
56 "stream": "stdout",
57 "text": [
57 "text": [
58 "Setup a handler to be called when a trait changes.\n",
58 "Setup a handler to be called when a trait changes.\n",
59 "\n",
59 "\n",
60 " This is used to setup dynamic notifications of trait changes.\n",
60 " This is used to setup dynamic notifications of trait changes.\n",
61 "\n",
61 "\n",
62 " Static handlers can be created by creating methods on a HasTraits\n",
62 " Static handlers can be created by creating methods on a HasTraits\n",
63 " subclass with the naming convention '_[traitname]_changed'. Thus,\n",
63 " subclass with the naming convention '_[traitname]_changed'. Thus,\n",
64 " to create static handler for the trait 'a', create the method\n",
64 " to create static handler for the trait 'a', create the method\n",
65 " _a_changed(self, name, old, new) (fewer arguments can be used, see\n",
65 " _a_changed(self, name, old, new) (fewer arguments can be used, see\n",
66 " below).\n",
66 " below).\n",
67 "\n",
67 "\n",
68 " Parameters\n",
68 " Parameters\n",
69 " ----------\n",
69 " ----------\n",
70 " handler : callable\n",
70 " handler : callable\n",
71 " A callable that is called when a trait changes. Its\n",
71 " A callable that is called when a trait changes. Its\n",
72 " signature can be handler(), handler(name), handler(name, new)\n",
72 " signature can be handler(), handler(name), handler(name, new)\n",
73 " or handler(name, old, new).\n",
73 " or handler(name, old, new).\n",
74 " name : list, str, None\n",
74 " name : list, str, None\n",
75 " If None, the handler will apply to all traits. If a list\n",
75 " If None, the handler will apply to all traits. If a list\n",
76 " of str, handler will apply to all names in the list. If a\n",
76 " of str, handler will apply to all names in the list. If a\n",
77 " str, the handler will apply just to that name.\n",
77 " str, the handler will apply just to that name.\n",
78 " remove : bool\n",
78 " remove : bool\n",
79 " If False (the default), then install the handler. If True\n",
79 " If False (the default), then install the handler. If True\n",
80 " then unintall it.\n",
80 " then unintall it.\n",
81 " \n"
81 " \n"
82 ]
82 ]
83 }
83 }
84 ],
84 ],
85 "prompt_number": 3
85 "prompt_number": 2
86 },
86 },
87 {
87 {
88 "cell_type": "markdown",
88 "cell_type": "markdown",
89 "metadata": {},
89 "metadata": {},
90 "source": [
90 "source": [
91 "Mentioned in the doc string, the callback registered can have 4 possible signatures:\n",
91 "Mentioned in the doc string, the callback registered can have 4 possible signatures:\n",
92 "\n",
92 "\n",
93 "- callback()\n",
93 "- callback()\n",
94 "- callback(trait_name)\n",
94 "- callback(trait_name)\n",
95 "- callback(trait_name, new_value)\n",
95 "- callback(trait_name, new_value)\n",
96 "- callback(trait_name, old_value, new_value)\n",
96 "- callback(trait_name, old_value, new_value)\n",
97 "\n",
97 "\n",
98 "An example of how to output an IntRangeWiget's value as it is changed can be seen below."
98 "An example of how to output an IntRangeWiget's value as it is changed can be seen below."
99 ]
99 ]
100 },
100 },
101 {
101 {
102 "cell_type": "code",
102 "cell_type": "code",
103 "collapsed": false,
103 "collapsed": false,
104 "input": [
104 "input": [
105 "intrange = widgets.IntRangeWidget()\n",
105 "intrange = widgets.IntRangeWidget()\n",
106 "display(intrange)\n",
106 "display(intrange)\n",
107 "\n",
107 "\n",
108 "def on_value_change(name, value):\n",
108 "def on_value_change(name, value):\n",
109 " print(value)\n",
109 " print(value)\n",
110 "\n",
110 "\n",
111 "intrange.on_trait_change(on_value_change, 'value')"
111 "intrange.on_trait_change(on_value_change, 'value')"
112 ],
112 ],
113 "language": "python",
113 "language": "python",
114 "metadata": {},
114 "metadata": {},
115 "outputs": [
115 "outputs": [
116 {
116 {
117 "output_type": "stream",
117 "output_type": "stream",
118 "stream": "stdout",
118 "stream": "stdout",
119 "text": [
119 "text": [
120 "1\n"
121 ]
122 },
123 {
124 "output_type": "stream",
125 "stream": "stdout",
126 "text": [
127 "2\n"
120 "2\n"
128 ]
121 ]
129 },
122 },
130 {
123 {
131 "output_type": "stream",
124 "output_type": "stream",
132 "stream": "stdout",
125 "stream": "stdout",
133 "text": [
126 "text": [
134 "3\n"
135 ]
136 },
137 {
138 "output_type": "stream",
139 "stream": "stdout",
140 "text": [
141 "4\n"
142 ]
143 },
144 {
145 "output_type": "stream",
146 "stream": "stdout",
147 "text": [
148 "5\n"
127 "5\n"
149 ]
128 ]
150 },
129 },
151 {
130 {
152 "output_type": "stream",
131 "output_type": "stream",
153 "stream": "stdout",
132 "stream": "stdout",
154 "text": [
133 "text": [
155 "6\n"
134 "10\n"
156 ]
157 },
158 {
159 "output_type": "stream",
160 "stream": "stdout",
161 "text": [
162 "7\n"
163 ]
164 },
165 {
166 "output_type": "stream",
167 "stream": "stdout",
168 "text": [
169 "8\n"
170 ]
135 ]
171 },
136 },
172 {
137 {
173 "output_type": "stream",
138 "output_type": "stream",
174 "stream": "stdout",
139 "stream": "stdout",
175 "text": [
140 "text": [
176 "9\n"
141 "11\n"
177 ]
142 ]
178 },
143 },
179 {
144 {
180 "output_type": "stream",
145 "output_type": "stream",
181 "stream": "stdout",
146 "stream": "stdout",
182 "text": [
147 "text": [
183 "10\n"
148 "13\n"
184 ]
149 ]
185 },
150 },
186 {
151 {
187 "output_type": "stream",
152 "output_type": "stream",
188 "stream": "stdout",
153 "stream": "stdout",
189 "text": [
154 "text": [
190 "11\n"
155 "14\n"
191 ]
156 ]
192 },
157 },
193 {
158 {
194 "output_type": "stream",
159 "output_type": "stream",
195 "stream": "stdout",
160 "stream": "stdout",
196 "text": [
161 "text": [
197 "12\n"
162 "16\n"
198 ]
163 ]
199 },
164 },
200 {
165 {
201 "output_type": "stream",
166 "output_type": "stream",
202 "stream": "stdout",
167 "stream": "stdout",
203 "text": [
168 "text": [
204 "13\n"
169 "18\n"
205 ]
170 ]
206 },
171 },
207 {
172 {
208 "output_type": "stream",
173 "output_type": "stream",
209 "stream": "stdout",
174 "stream": "stdout",
210 "text": [
175 "text": [
211 "14\n"
176 "20\n"
212 ]
177 ]
213 },
178 },
214 {
179 {
215 "output_type": "stream",
180 "output_type": "stream",
216 "stream": "stdout",
181 "stream": "stdout",
217 "text": [
182 "text": [
218 "15\n"
183 "22\n"
219 ]
184 ]
220 },
185 },
221 {
186 {
222 "output_type": "stream",
187 "output_type": "stream",
223 "stream": "stdout",
188 "stream": "stdout",
224 "text": [
189 "text": [
225 "16\n"
190 "24\n"
226 ]
191 ]
227 },
192 },
228 {
193 {
229 "output_type": "stream",
194 "output_type": "stream",
230 "stream": "stdout",
195 "stream": "stdout",
231 "text": [
196 "text": [
232 "17\n"
197 "26\n"
233 ]
198 ]
234 },
199 },
235 {
200 {
236 "output_type": "stream",
201 "output_type": "stream",
237 "stream": "stdout",
202 "stream": "stdout",
238 "text": [
203 "text": [
239 "18\n"
204 "29\n"
240 ]
205 ]
241 },
206 },
242 {
207 {
243 "output_type": "stream",
208 "output_type": "stream",
244 "stream": "stdout",
209 "stream": "stdout",
245 "text": [
210 "text": [
246 "20\n"
211 "30\n"
247 ]
212 ]
248 },
213 },
249 {
214 {
250 "output_type": "stream",
215 "output_type": "stream",
251 "stream": "stdout",
216 "stream": "stdout",
252 "text": [
217 "text": [
253 "19\n"
218 "33\n"
254 ]
219 ]
255 },
220 },
256 {
221 {
257 "output_type": "stream",
222 "output_type": "stream",
258 "stream": "stdout",
223 "stream": "stdout",
259 "text": [
224 "text": [
260 "18\n"
225 "36\n"
261 ]
226 ]
262 },
227 },
263 {
228 {
264 "output_type": "stream",
229 "output_type": "stream",
265 "stream": "stdout",
230 "stream": "stdout",
266 "text": [
231 "text": [
267 "17\n"
232 "38\n"
268 ]
233 ]
269 },
234 },
270 {
235 {
271 "output_type": "stream",
236 "output_type": "stream",
272 "stream": "stdout",
237 "stream": "stdout",
273 "text": [
238 "text": [
274 "16\n"
239 "42\n"
275 ]
240 ]
276 },
241 },
277 {
242 {
278 "output_type": "stream",
243 "output_type": "stream",
279 "stream": "stdout",
244 "stream": "stdout",
280 "text": [
245 "text": [
281 "12\n"
246 "45\n"
282 ]
247 ]
283 },
248 },
284 {
249 {
285 "output_type": "stream",
250 "output_type": "stream",
286 "stream": "stdout",
251 "stream": "stdout",
287 "text": [
252 "text": [
288 "10\n"
253 "46\n"
289 ]
254 ]
290 },
255 },
291 {
256 {
292 "output_type": "stream",
257 "output_type": "stream",
293 "stream": "stdout",
258 "stream": "stdout",
294 "text": [
259 "text": [
295 "8\n"
260 "48\n"
296 ]
261 ]
297 },
262 },
298 {
263 {
299 "output_type": "stream",
264 "output_type": "stream",
300 "stream": "stdout",
265 "stream": "stdout",
301 "text": [
266 "text": [
302 "6\n"
267 "50\n"
303 ]
268 ]
304 },
269 },
305 {
270 {
306 "output_type": "stream",
271 "output_type": "stream",
307 "stream": "stdout",
272 "stream": "stdout",
308 "text": [
273 "text": [
309 "4\n"
274 "51\n"
310 ]
275 ]
311 },
276 },
312 {
277 {
313 "output_type": "stream",
278 "output_type": "stream",
314 "stream": "stdout",
279 "stream": "stdout",
315 "text": [
280 "text": [
316 "3\n"
281 "52\n"
317 ]
282 ]
318 },
283 },
319 {
284 {
320 "output_type": "stream",
285 "output_type": "stream",
321 "stream": "stdout",
286 "stream": "stdout",
322 "text": [
287 "text": [
323 "2\n"
288 "53\n"
324 ]
289 ]
325 },
290 },
326 {
291 {
327 "output_type": "stream",
292 "output_type": "stream",
328 "stream": "stdout",
293 "stream": "stdout",
329 "text": [
294 "text": [
330 "1\n"
295 "54\n"
331 ]
296 ]
332 },
297 },
333 {
298 {
334 "output_type": "stream",
299 "output_type": "stream",
335 "stream": "stdout",
300 "stream": "stdout",
336 "text": [
301 "text": [
337 "4\n"
302 "52\n"
338 ]
303 ]
339 },
304 },
340 {
305 {
341 "output_type": "stream",
306 "output_type": "stream",
342 "stream": "stdout",
307 "stream": "stdout",
343 "text": [
308 "text": [
344 "10\n"
309 "50\n"
345 ]
310 ]
346 },
311 },
347 {
312 {
348 "output_type": "stream",
313 "output_type": "stream",
349 "stream": "stdout",
314 "stream": "stdout",
350 "text": [
315 "text": [
351 "18\n"
316 "48\n"
352 ]
317 ]
353 },
318 },
354 {
319 {
355 "output_type": "stream",
320 "output_type": "stream",
356 "stream": "stdout",
321 "stream": "stdout",
357 "text": [
322 "text": [
358 "39\n"
323 "44\n"
359 ]
324 ]
360 },
325 },
361 {
326 {
362 "output_type": "stream",
327 "output_type": "stream",
363 "stream": "stdout",
328 "stream": "stdout",
364 "text": [
329 "text": [
365 "60\n"
330 "41\n"
366 ]
331 ]
367 },
332 },
368 {
333 {
369 "output_type": "stream",
334 "output_type": "stream",
370 "stream": "stdout",
335 "stream": "stdout",
371 "text": [
336 "text": [
372 "68\n"
337 "34\n"
373 ]
338 ]
374 },
339 },
375 {
340 {
376 "output_type": "stream",
341 "output_type": "stream",
377 "stream": "stdout",
342 "stream": "stdout",
378 "text": [
343 "text": [
379 "75\n"
344 "30\n"
380 ]
345 ]
381 },
346 },
382 {
347 {
383 "output_type": "stream",
348 "output_type": "stream",
384 "stream": "stdout",
349 "stream": "stdout",
385 "text": [
350 "text": [
386 "79\n"
351 "28\n"
387 ]
352 ]
388 },
353 },
389 {
354 {
390 "output_type": "stream",
355 "output_type": "stream",
391 "stream": "stdout",
356 "stream": "stdout",
392 "text": [
357 "text": [
393 "82\n"
358 "26\n"
394 ]
359 ]
395 },
360 },
396 {
361 {
397 "output_type": "stream",
362 "output_type": "stream",
398 "stream": "stdout",
363 "stream": "stdout",
399 "text": [
364 "text": [
400 "85\n"
365 "25\n"
401 ]
366 ]
402 },
367 },
403 {
368 {
404 "output_type": "stream",
369 "output_type": "stream",
405 "stream": "stdout",
370 "stream": "stdout",
406 "text": [
371 "text": [
407 "86\n"
372 "24\n"
408 ]
373 ]
409 }
374 }
410 ],
375 ],
411 "prompt_number": 5
376 "prompt_number": 3
412 },
377 },
413 {
378 {
414 "cell_type": "heading",
379 "cell_type": "heading",
415 "level": 1,
380 "level": 1,
416 "metadata": {},
381 "metadata": {},
417 "source": [
382 "source": [
418 "Specialized Events"
383 "Specialized Events"
419 ]
384 ]
420 },
385 },
421 {
386 {
422 "cell_type": "heading",
387 "cell_type": "heading",
423 "level": 2,
388 "level": 2,
424 "metadata": {},
389 "metadata": {},
425 "source": [
390 "source": [
426 "Button On Click Event"
391 "Button On Click Event"
427 ]
392 ]
428 },
393 },
429 {
394 {
430 "cell_type": "markdown",
395 "cell_type": "markdown",
431 "metadata": {},
396 "metadata": {},
432 "source": [
397 "source": [
433 "The `ButtonWidget` is a special widget, like the `ContainerWidget` and `MulticontainerWidget`, that isn't used to represent a data type. Instead the button widget is used to handle mouse clicks. The `on_click` method of the `ButtonWidget` can be used to register a click even handler. The doc string of the `on_click` can be seen below."
398 "The `ButtonWidget` is a special widget, like the `ContainerWidget` and `MulticontainerWidget`, that isn't used to represent a data type. Instead the button widget is used to handle mouse clicks. The `on_click` method of the `ButtonWidget` can be used to register a click even handler. The doc string of the `on_click` can be seen below."
434 ]
399 ]
435 },
400 },
436 {
401 {
437 "cell_type": "code",
402 "cell_type": "code",
438 "collapsed": false,
403 "collapsed": false,
439 "input": [
404 "input": [
440 "print(widgets.ButtonWidget.on_click.__doc__)"
405 "print(widgets.ButtonWidget.on_click.__doc__)"
441 ],
406 ],
442 "language": "python",
407 "language": "python",
443 "metadata": {},
408 "metadata": {},
444 "outputs": [
409 "outputs": [
445 {
410 {
446 "output_type": "stream",
411 "output_type": "stream",
447 "stream": "stdout",
412 "stream": "stdout",
448 "text": [
413 "text": [
449 "Register a callback to execute when the button is clicked. The\n",
414 "Register a callback to execute when the button is clicked. The\n",
450 " callback can either accept no parameters or one sender parameter:\n",
415 " callback can either accept no parameters or one sender parameter:\n",
451 " - callback()\n",
416 " - callback()\n",
452 " - callback(sender)\n",
417 " - callback(sender)\n",
453 " If the callback has a sender parameter, the ButtonWidget instance that\n",
418 " If the callback has a sender parameter, the ButtonWidget instance that\n",
454 " called the callback will be passed into the method as the sender.\n",
419 " called the callback will be passed into the method as the sender.\n",
455 "\n",
420 "\n",
456 " Parameters\n",
421 " Parameters\n",
457 " ----------\n",
422 " ----------\n",
458 " remove : bool (optional)\n",
423 " remove : bool (optional)\n",
459 " Set to true to remove the callback from the list of callbacks.\n"
424 " Set to true to remove the callback from the list of callbacks.\n"
460 ]
425 ]
461 }
426 }
462 ],
427 ],
463 "prompt_number": 6
428 "prompt_number": 4
464 },
429 },
465 {
430 {
466 "cell_type": "markdown",
431 "cell_type": "markdown",
467 "metadata": {},
432 "metadata": {},
468 "source": [
433 "source": [
469 "Button clicks are transmitted from the front-end to the back-end using custom messages. By using the `on_click` method, a button that prints a message when it has been clicked is shown below."
434 "Button clicks are transmitted from the front-end to the back-end using custom messages. By using the `on_click` method, a button that prints a message when it has been clicked is shown below."
470 ]
435 ]
471 },
436 },
472 {
437 {
473 "cell_type": "code",
438 "cell_type": "code",
474 "collapsed": false,
439 "collapsed": false,
475 "input": [
440 "input": [
476 "display(intrange)\n",
441 "display(intrange)\n",
477 "print('hi')"
442 "print('hi')"
478 ],
443 ],
479 "language": "python",
444 "language": "python",
480 "metadata": {},
445 "metadata": {},
481 "outputs": [
446 "outputs": [
482 {
447 {
483 "output_type": "stream",
448 "output_type": "stream",
484 "stream": "stdout",
449 "stream": "stdout",
485 "text": [
450 "text": [
486 "hi\n"
451 "hi\n"
487 ]
452 ]
488 },
453 },
489 {
454 {
490 "output_type": "stream",
455 "output_type": "stream",
491 "stream": "stdout",
456 "stream": "stdout",
492 "text": [
457 "text": [
493 "85\n"
458 "23\n"
494 ]
495 },
496 {
497 "output_type": "stream",
498 "stream": "stdout",
499 "text": [
500 "84\n"
501 ]
502 },
503 {
504 "output_type": "stream",
505 "stream": "stdout",
506 "text": [
507 "81\n"
508 ]
509 },
510 {
511 "output_type": "stream",
512 "stream": "stdout",
513 "text": [
514 "79\n"
515 ]
459 ]
516 },
460 },
517 {
461 {
518 "output_type": "stream",
462 "output_type": "stream",
519 "stream": "stdout",
463 "stream": "stdout",
520 "text": [
464 "text": [
521 "73\n"
465 "24\n"
522 ]
466 ]
523 },
467 },
524 {
468 {
525 "output_type": "stream",
469 "output_type": "stream",
526 "stream": "stdout",
470 "stream": "stdout",
527 "text": [
471 "text": [
528 "70\n"
472 "28\n"
529 ]
473 ]
530 },
474 },
531 {
475 {
532 "output_type": "stream",
476 "output_type": "stream",
533 "stream": "stdout",
477 "stream": "stdout",
534 "text": [
478 "text": [
535 "67\n"
479 "30\n"
536 ]
480 ]
537 },
481 },
538 {
482 {
539 "output_type": "stream",
483 "output_type": "stream",
540 "stream": "stdout",
484 "stream": "stdout",
541 "text": [
485 "text": [
542 "59\n"
486 "37\n"
543 ]
487 ]
544 },
488 },
545 {
489 {
546 "output_type": "stream",
490 "output_type": "stream",
547 "stream": "stdout",
491 "stream": "stdout",
548 "text": [
492 "text": [
549 "56\n"
493 "39\n"
550 ]
494 ]
551 },
495 },
552 {
496 {
553 "output_type": "stream",
497 "output_type": "stream",
554 "stream": "stdout",
498 "stream": "stdout",
555 "text": [
499 "text": [
556 "53\n"
500 "41\n"
557 ]
501 ]
558 },
502 },
559 {
503 {
560 "output_type": "stream",
504 "output_type": "stream",
561 "stream": "stdout",
505 "stream": "stdout",
562 "text": [
506 "text": [
563 "51\n"
507 "44\n"
564 ]
508 ]
565 },
509 },
566 {
510 {
567 "output_type": "stream",
511 "output_type": "stream",
568 "stream": "stdout",
512 "stream": "stdout",
569 "text": [
513 "text": [
570 "49\n"
514 "46\n"
571 ]
515 ]
572 },
516 },
573 {
517 {
574 "output_type": "stream",
518 "output_type": "stream",
575 "stream": "stdout",
519 "stream": "stdout",
576 "text": [
520 "text": [
577 "47\n"
521 "48\n"
578 ]
522 ]
579 },
523 },
580 {
524 {
581 "output_type": "stream",
525 "output_type": "stream",
582 "stream": "stdout",
526 "stream": "stdout",
583 "text": [
527 "text": [
584 "45\n"
528 "50\n"
585 ]
529 ]
586 },
530 },
587 {
531 {
588 "output_type": "stream",
532 "output_type": "stream",
589 "stream": "stdout",
533 "stream": "stdout",
590 "text": [
534 "text": [
591 "44\n"
535 "51\n"
592 ]
536 ]
593 },
537 },
594 {
538 {
595 "output_type": "stream",
539 "output_type": "stream",
596 "stream": "stdout",
540 "stream": "stdout",
597 "text": [
541 "text": [
598 "42\n"
542 "53\n"
599 ]
543 ]
600 }
544 }
601 ],
545 ],
602 "prompt_number": 7
546 "prompt_number": 5
603 },
547 },
604 {
548 {
605 "cell_type": "code",
549 "cell_type": "code",
606 "collapsed": false,
550 "collapsed": false,
607 "input": [
551 "input": [
608 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
552 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
609 "display(button)\n",
553 "display(button)\n",
610 "\n",
554 "\n",
611 "def on_button_clicked(sender):\n",
555 "def on_button_clicked(sender):\n",
612 " print(\"Button clicked.\")\n",
556 " print(\"Button clicked.\")\n",
613 " intrange.value +=1\n",
557 " intrange.value +=1\n",
614 "\n",
558 "\n",
615 "button.on_click(on_button_clicked)"
559 "button.on_click(on_button_clicked)"
616 ],
560 ],
617 "language": "python",
561 "language": "python",
618 "metadata": {},
562 "metadata": {},
619 "outputs": [
563 "outputs": [
620 {
564 {
621 "output_type": "stream",
565 "output_type": "stream",
622 "stream": "stdout",
566 "stream": "stdout",
623 "text": [
567 "text": [
624 "Button clicked.\n",
568 "Button clicked.\n",
625 "43\n"
569 "54\n"
626 ]
627 },
628 {
629 "output_type": "stream",
630 "stream": "stdout",
631 "text": [
632 "Button clicked.\n",
633 "44\n"
634 ]
570 ]
635 },
571 },
636 {
572 {
637 "output_type": "stream",
573 "output_type": "stream",
638 "stream": "stdout",
574 "stream": "stdout",
639 "text": [
575 "text": [
640 "Button clicked.\n",
576 "Button clicked.\n",
641 "45\n"
577 "55\n"
642 ]
578 ]
643 },
579 },
644 {
580 {
645 "output_type": "stream",
581 "output_type": "stream",
646 "stream": "stdout",
582 "stream": "stdout",
647 "text": [
583 "text": [
648 "Button clicked.\n",
584 "Button clicked.\n",
649 "46\n"
585 "56\n"
650 ]
651 },
652 {
653 "output_type": "stream",
654 "stream": "stdout",
655 "text": [
656 "Button clicked.\n",
657 "47\n"
658 ]
659 },
660 {
661 "output_type": "stream",
662 "stream": "stdout",
663 "text": [
664 "Button clicked.\n",
665 "48\n"
666 ]
667 },
668 {
669 "output_type": "stream",
670 "stream": "stdout",
671 "text": [
672 "Button clicked.\n",
673 "49\n"
674 ]
586 ]
675 }
587 }
676 ],
588 ],
677 "prompt_number": 8
589 "prompt_number": 6
678 },
590 },
679 {
591 {
680 "cell_type": "markdown",
592 "cell_type": "markdown",
681 "metadata": {},
593 "metadata": {},
682 "source": [
594 "source": [
683 "Event handlers can also be used to create widgets. In the example below, clicking a button spawns another button with a description equal to how many times the parent button had been clicked at the time."
595 "Event handlers can also be used to create widgets. In the example below, clicking a button spawns another button with a description equal to how many times the parent button had been clicked at the time."
684 ]
596 ]
685 },
597 },
686 {
598 {
687 "cell_type": "code",
599 "cell_type": "code",
688 "collapsed": false,
600 "collapsed": false,
689 "input": [],
601 "input": [],
690 "language": "python",
602 "language": "python",
691 "metadata": {},
603 "metadata": {},
692 "outputs": [
604 "outputs": [
693 {
605 {
694 "metadata": {},
606 "metadata": {},
695 "output_type": "pyout",
607 "output_type": "pyout",
696 "prompt_number": 11,
608 "prompt_number": 11,
697 "text": [
609 "text": [
698 "{'content': {'data': \"{'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', 'content': {u'data': {u'method': u'custom', u'custom_content': {u'event': u'click'}}, u'comm_id': u'eea5f11ae7aa473993dd0c81d6016648'}, 'header': {u'username': u'username', u'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', u'msg_type': u'comm_msg', u'session': u'0F6D6BE728DA47A38CFC4BDEACF34FC4'}, 'buffers': [], 'metadata': {}}\\ncustom message {'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', 'content': {u'data': {u'method': u'custom', u'custom_content': {u'event': u'click'}}, u'comm_id': u'eea5f11ae7aa473993dd0c81d6016648'}, 'header': {u'username': u'username', u'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', u'msg_type': u'comm_msg', u'session': u'0F6D6BE728DA47A38CFC4BDEACF34FC4'}, 'buffers': [], 'metadata': {}}\\nhandling click\\n{u'event': u'click'}\\nButton clicked.\\n2\\n\",\n",
610 "{'content': {'data': \"{'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', 'content': {u'data': {u'method': u'custom', u'custom_content': {u'event': u'click'}}, u'comm_id': u'eea5f11ae7aa473993dd0c81d6016648'}, 'header': {u'username': u'username', u'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', u'msg_type': u'comm_msg', u'session': u'0F6D6BE728DA47A38CFC4BDEACF34FC4'}, 'buffers': [], 'metadata': {}}\\ncustom message {'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', 'content': {u'data': {u'method': u'custom', u'custom_content': {u'event': u'click'}}, u'comm_id': u'eea5f11ae7aa473993dd0c81d6016648'}, 'header': {u'username': u'username', u'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', u'msg_type': u'comm_msg', u'session': u'0F6D6BE728DA47A38CFC4BDEACF34FC4'}, 'buffers': [], 'metadata': {}}\\nhandling click\\n{u'event': u'click'}\\nButton clicked.\\n2\\n\",\n",
699 " 'name': 'stdout'},\n",
611 " 'name': 'stdout'},\n",
700 " 'header': {'msg_id': 'd9dc144a-d86c-42c1-8bab-f8a6bc525723',\n",
612 " 'header': {'msg_id': 'd9dc144a-d86c-42c1-8bab-f8a6bc525723',\n",
701 " 'msg_type': 'stream',\n",
613 " 'msg_type': 'stream',\n",
702 " 'session': '9b9408d8-7420-4e0c-976d-cdda9f8d2564',\n",
614 " 'session': '9b9408d8-7420-4e0c-976d-cdda9f8d2564',\n",
703 " 'username': 'kernel'},\n",
615 " 'username': 'kernel'},\n",
704 " 'metadata': {},\n",
616 " 'metadata': {},\n",
705 " 'msg_id': 'd9dc144a-d86c-42c1-8bab-f8a6bc525723',\n",
617 " 'msg_id': 'd9dc144a-d86c-42c1-8bab-f8a6bc525723',\n",
706 " 'msg_type': 'stream',\n",
618 " 'msg_type': 'stream',\n",
707 " 'parent_header': {'msg_id': '3DBB06AD83C942DD85DC6477B08F1FBF',\n",
619 " 'parent_header': {'msg_id': '3DBB06AD83C942DD85DC6477B08F1FBF',\n",
708 " 'msg_type': 'comm_msg',\n",
620 " 'msg_type': 'comm_msg',\n",
709 " 'session': '0F6D6BE728DA47A38CFC4BDEACF34FC4',\n",
621 " 'session': '0F6D6BE728DA47A38CFC4BDEACF34FC4',\n",
710 " 'username': 'username'}}"
622 " 'username': 'username'}}"
711 ]
623 ]
712 }
624 }
713 ],
625 ],
714 "prompt_number": 11
626 "prompt_number": 11
715 },
627 },
716 {
628 {
717 "cell_type": "code",
629 "cell_type": "code",
718 "collapsed": false,
630 "collapsed": false,
719 "input": [
631 "input": [
720 "def show_button(sender=None):\n",
632 "def show_button(sender=None):\n",
721 " button = widgets.ButtonWidget()\n",
633 " button = widgets.ButtonWidget()\n",
722 " button.clicks = 0\n",
634 " button.clicks = 0\n",
723 " if sender is None:\n",
635 " if sender is None:\n",
724 " button.description = \"0\"\n",
636 " button.description = \"0\"\n",
725 " else:\n",
637 " else:\n",
726 " sender.clicks += 1\n",
638 " sender.clicks += 1\n",
727 " button.description = \"%d\" % sender.clicks\n",
639 " button.description = \"%d\" % sender.clicks\n",
728 " display(button)\n",
640 " display(button)\n",
729 " button.on_click(show_button)\n",
641 " button.on_click(show_button)\n",
730 "show_button()\n",
642 "show_button()\n",
731 " "
643 " "
732 ],
644 ],
733 "language": "python",
645 "language": "python",
734 "metadata": {},
646 "metadata": {},
735 "outputs": [],
647 "outputs": [],
736 "prompt_number": 9
648 "prompt_number": 7
737 },
649 },
738 {
650 {
739 "cell_type": "code",
651 "cell_type": "code",
740 "collapsed": false,
652 "collapsed": false,
741 "input": [],
653 "input": [],
742 "language": "python",
654 "language": "python",
743 "metadata": {},
655 "metadata": {},
744 "outputs": []
656 "outputs": []
745 }
657 }
746 ],
658 ],
747 "metadata": {}
659 "metadata": {}
748 }
660 }
749 ]
661 ]
750 } No newline at end of file
662 }
General Comments 0
You need to be logged in to leave comments. Login now