##// END OF EJS Templates
rebuild example notebooks...
MinRK -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
This diff has been collapsed as it changes many lines, (708 lines changed) Show them Hide them
@@ -3,480 +3,600 b''
3 3 "name": "01_notebook_introduction"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
11 "cell_type": "heading",
12 "level": 1,
13 "metadata": {},
14 "source": [
15 "An introduction to the IPython notebook"
16 ]
17 },
18 {
10 19 "cell_type": "markdown",
20 "metadata": {},
11 21 "source": [
12 "# An introduction to the IPython notebook",
13 "",
14 "The IPython web notebook is a frontend that allows for new modes",
15 "of interaction with IPython: this web-based interface allows you to execute Python and IPython",
16 "commands in each input cell just like you would at the IPython terminal or Qt console, but you can",
17 "also save an entire session as a document in a file with the `.ipynb` extension.",
18 "",
19 "The document you are reading now is precisely an example of one such notebook, and we will show you",
20 "here how to best use this new interface.",
21 "",
22 "The first thing to understand is that a notebook consists of a sequence of 'cells' that can contain ",
23 "either text (such as this one) or code meant for execution (such as the next one):",
24 "",
25 "* Text cells can be written using [Markdown syntax](http://daringfireball.net/projects/markdown/syntax) ",
26 "(in a future release we will also provide support for reStructuredText and Sphinx integration, and we ",
27 "welcome help from interested contributors to make that happen).",
28 "",
29 "* Code cells take IPython input (i.e. Python code, `%magics`, `!system calls`, etc) like IPython at",
30 "the terminal or at the Qt Console. The only difference is that in order to execute a cell, you *must*",
31 "use `Shift-Enter`, as pressing `Enter` will add a new line of text to the cell. When you type ",
32 "`Shift-Enter`, the cell content is executed, output displayed and a new cell is created below. Try",
22 "\n",
23 "The IPython web notebook is a frontend that allows for new modes\n",
24 "of interaction with IPython: this web-based interface allows you to execute Python and IPython\n",
25 "commands in each input cell just like you would at the IPython terminal or Qt console, but you can\n",
26 "also save an entire session as a document in a file with the `.ipynb` extension.\n",
27 "\n",
28 "The document you are reading now is precisely an example of one such notebook, and we will show you\n",
29 "here how to best use this new interface.\n",
30 "\n",
31 "The first thing to understand is that a notebook consists of a sequence of 'cells' that can contain \n",
32 "either text (such as this one) or code meant for execution (such as the next one):\n",
33 "\n",
34 "* Text cells can be written using [Markdown syntax](http://daringfireball.net/projects/markdown/syntax) \n",
35 "(in a future release we will also provide support for reStructuredText and Sphinx integration, and we \n",
36 "welcome help from interested contributors to make that happen).\n",
37 "\n",
38 "* Code cells take IPython input (i.e. Python code, `%magics`, `!system calls`, etc) like IPython at\n",
39 "the terminal or at the Qt Console. The only difference is that in order to execute a cell, you *must*\n",
40 "use `Shift-Enter`, as pressing `Enter` will add a new line of text to the cell. When you type \n",
41 "`Shift-Enter`, the cell content is executed, output displayed and a new cell is created below. Try\n",
33 42 "it now by putting your cursor on the next cell and typing `Shift-Enter`:"
34 43 ]
35 44 },
36 45 {
37 46 "cell_type": "code",
47 "collapsed": false,
38 48 "input": [
39 49 "\"This is the new IPython notebook\""
40 50 ],
41 51 "language": "python",
52 "metadata": {},
42 53 "outputs": [
43 54 {
44 55 "output_type": "pyout",
45 "prompt_number": 1,
56 "prompt_number": 2,
46 57 "text": [
47 58 "'This is the new IPython notebook'"
48 59 ]
49 60 }
50 61 ],
51 "prompt_number": 1
62 "prompt_number": 2
52 63 },
53 64 {
54 65 "cell_type": "markdown",
66 "metadata": {},
55 67 "source": [
56 "You can re-execute the same cell over and over as many times as you want. Simply put your",
57 "cursor in the cell again, edit at will, and type `Shift-Enter` to execute. ",
58 "",
59 "**Tip:** A cell can also be executed",
60 "*in-place*, where IPython executes its content but leaves the cursor in the same cell. This is done by",
61 "typing `Ctrl-Enter` instead, and is useful if you want to quickly run a command to check something ",
62 "before tping the real content you want to leave in the cell. For example, in the next cell, try issuing",
68 "You can re-execute the same cell over and over as many times as you want. Simply put your\n",
69 "cursor in the cell again, edit at will, and type `Shift-Enter` to execute. \n",
70 "\n",
71 "**Tip:** A cell can also be executed\n",
72 "*in-place*, where IPython executes its content but leaves the cursor in the same cell. This is done by\n",
73 "typing `Ctrl-Enter` instead, and is useful if you want to quickly run a command to check something \n",
74 "before tping the real content you want to leave in the cell. For example, in the next cell, try issuing\n",
63 75 "several system commands in-place with `Ctrl-Enter`, such as `pwd` and then `ls`:"
64 76 ]
65 77 },
66 78 {
67 79 "cell_type": "code",
80 "collapsed": false,
68 81 "input": [
69 82 "ls"
70 83 ],
71 84 "language": "python",
85 "metadata": {},
72 86 "outputs": [
73 87 {
74 88 "output_type": "stream",
75 89 "stream": "stdout",
76 90 "text": [
77 "00_notebook_tour.ipynb formatting.ipynb sympy_quantum_computing.ipynb",
78 "01_notebook_introduction.ipynb python-logo.svg trapezoid_rule.ipynb",
79 "display_protocol.ipynb sympy.ipynb"
91 "00_notebook_tour.ipynb callbacks.ipynb python-logo.svg\r\n",
92 "01_notebook_introduction.ipynb cython_extension.ipynb rmagic_extension.ipynb\r\n",
93 "Animations_and_Progress.ipynb display_protocol.ipynb sympy.ipynb\r\n",
94 "Capturing Output.ipynb formatting.ipynb sympy_quantum_computing.ipynb\r\n",
95 "Script Magics.ipynb octavemagic_extension.ipynb trapezoid_rule.ipynb\r\n",
96 "animation.m4v progbar.ipynb\r\n"
80 97 ]
81 98 }
82 99 ],
83 "prompt_number": 2
100 "prompt_number": 3
84 101 },
85 102 {
86 103 "cell_type": "markdown",
104 "metadata": {},
87 105 "source": [
88 "In a cell, you can type anything from a single python expression to an arbitrarily long amount of code ",
106 "In a cell, you can type anything from a single python expression to an arbitrarily long amount of code \n",
89 107 "(although for reasons of readability, you should probably limit this to a few dozen lines):"
90 108 ]
91 109 },
92 110 {
93 111 "cell_type": "code",
112 "collapsed": false,
94 113 "input": [
95 "def f(x):",
96 " \"\"\"My function",
97 " x : parameter\"\"\"",
98 " ",
99 " return x+1",
100 "",
114 "def f(x):\n",
115 " \"\"\"My function\n",
116 " x : parameter\"\"\"\n",
117 " \n",
118 " return x+1\n",
119 "\n",
101 120 "print \"f(3) = \", f(3)"
102 121 ],
103 122 "language": "python",
123 "metadata": {},
104 124 "outputs": [
105 125 {
106 126 "output_type": "stream",
107 127 "stream": "stdout",
108 128 "text": [
109 "f(3) = 4"
129 "f(3) = 4\n"
110 130 ]
111 131 }
112 132 ],
113 "prompt_number": 3
133 "prompt_number": 4
134 },
135 {
136 "cell_type": "heading",
137 "level": 2,
138 "metadata": {},
139 "source": [
140 "User interface"
141 ]
114 142 },
115 143 {
116 144 "cell_type": "markdown",
145 "metadata": {},
117 146 "source": [
118 "## User interface",
119 "",
120 "When you start a new notebook server with `ipython notebook`, your",
121 "browser should open into the *Dashboard*, a page listing all notebooks",
122 "available in the current directory as well as letting you create new",
123 "notebooks. In this page, you can also drag and drop existing `.py` files",
124 "over the file list to import them as notebooks (see the manual for ",
125 "[further details on how these files are ",
126 "interpreted](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html)).",
127 "",
128 "Once you open an existing notebook (like this one) or create a new one,",
129 "you are in the main notebook interface, which consists of a main editing",
130 "area (where these cells are contained) as well as a collapsible left panel, ",
131 "a permanent header area at the top, and a pager that rises from the",
147 "When you start a new notebook server with `ipython notebook`, your\n",
148 "browser should open into the *Dashboard*, a page listing all notebooks\n",
149 "available in the current directory as well as letting you create new\n",
150 "notebooks. In this page, you can also drag and drop existing `.py` files\n",
151 "over the file list to import them as notebooks (see the manual for \n",
152 "[further details on how these files are \n",
153 "interpreted](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html)).\n",
154 "\n",
155 "Once you open an existing notebook (like this one) or create a new one,\n",
156 "you are in the main notebook interface, which consists of a main editing\n",
157 "area (where these cells are contained) as well as a menu and \n",
158 "permanent header area at the top, and a pager that rises from the\n",
132 159 "bottom when needed and can be collapsed again."
133 160 ]
134 161 },
135 162 {
163 "cell_type": "heading",
164 "level": 3,
165 "metadata": {},
166 "source": [
167 "Main editing area"
168 ]
169 },
170 {
136 171 "cell_type": "markdown",
172 "metadata": {},
137 173 "source": [
138 "### Main editing area",
139 "",
140 "Here, you can move with the arrow keys or using the ",
141 "scroll bars. The cursor enters code cells immediately, but only selects",
142 "text (markdown) cells without entering in them; to enter a text cell,",
143 "use `Enter`, and `Shift-Enter` to exit it again (just like to execute a ",
174 "Here, you can move with the arrow keys or using the \n",
175 "scroll bars. The cursor enters code cells immediately, but only selects\n",
176 "text (markdown) cells without entering in them; to enter a text cell,\n",
177 "use `Enter` (or double-click), and `Shift-Enter` to exit it again (just like to execute a \n",
144 178 "code cell)."
145 179 ]
146 180 },
147 181 {
182 "cell_type": "heading",
183 "level": 3,
184 "metadata": {},
185 "source": [
186 "Menu"
187 ]
188 },
189 {
148 190 "cell_type": "markdown",
191 "metadata": {},
192 "source": [
193 "The menu bar conains all the commands you can use to manipulate the notebook.\n",
194 "\n",
195 "The *File* menu has the usual open/save file operations, as well as Export,\n",
196 "for downloading the notebook to your computer.\n",
197 "\n",
198 "*Edit* has controls for cut/copy/paste, and moving cells around.\n",
199 "\n",
200 "*View* lets you toggle visibility of the header elements,\n",
201 "to recover precious screen real estate.\n",
202 "\n",
203 "The *Cell* menu lets you manipulate individual cells,\n",
204 "and the names should be fairly self-explanatory.\n",
205 "\n",
206 "The *Kernel* menu lets you signal the kernel executing your code. \n",
207 "`Interrupt` does the equivalent of hitting `Ctrl-C` at a terminal, and\n",
208 "`Restart` fully kills the kernel process and starts a fresh one. Obviously\n",
209 "this means that all your previous variables are destroyed, but it also\n",
210 "makes it easy to get a fresh kernel in which to re-execute a notebook, perhaps\n",
211 "after changing an extension module for which Python's `reload` mechanism\n",
212 "does not work.\n",
213 "\n",
214 "The *Help* menu contains links to the documentation of some projects\n",
215 "closely related to IPython as well as the minimal keybindings you need to\n",
216 "know. But you should use `Ctrl-m h` (or click the `QuickHelp` button at\n",
217 "the top) and learn some of the other keybindings, as it will make your \n",
218 "workflow much more fluid and efficient.\n",
219 "\n",
220 "You will also see a few buttons there for common actions,\n",
221 "and hovering over each button will tell you which command they correspond to,\n",
222 "if the icons are not clear enough."
223 ]
224 },
225 {
226 "cell_type": "heading",
227 "level": 3,
228 "metadata": {},
149 229 "source": [
150 "### Left panel",
151 "",
152 "This panel contains a number of panes that can be",
153 "collapsed vertically by clicking on their title bar, and the whole panel",
154 "can also be collapsed by clicking on the vertical divider (note that you",
155 "can not *drag* the divider, for now you can only click on it).",
156 "",
157 "The *Notebook* section contains actions that pertain to the whole notebook,",
158 "such as downloading the current notebook either in its original format",
159 "or as a `.py` script, and printing it. When you click the `Print` button,",
160 "a new HTML page opens with a static copy of the notebook; you can then",
161 "use your web browser's mechanisms to save or print this file.",
162 "",
163 "The *Cell* section lets you manipulate individual cells, and the names should ",
164 "be fairly self-explanatory.",
165 "",
166 "The *Kernel* section lets you signal the kernel executing your code. ",
167 "`Interrupt` does the equivalent of hitting `Ctrl-C` at a terminal, and",
168 "`Restart` fully kills the kernel process and starts a fresh one. Obviously",
169 "this means that all your previous variables are destroyed, but it also",
170 "makes it easy to get a fresh kernel in which to re-execute a notebook, perhaps",
171 "after changing an extension module for which Python's `reload` mechanism",
172 "does not work. If you check the 'Kill kernel upon exit' box, when you ",
173 "close the page IPython will automatically shut down the running kernel;",
174 "otherwise the kernels won't close until you stop the whole ",
175 "",
176 "The *Help* section contains links to the documentation of some projects",
177 "closely related to IPython as well as the minimal keybindings you need to",
178 "know. But you should use `Ctrl-m h` (or click the `QuickHelp` button at",
179 "the top) and learn some of the other keybindings, as it will make your ",
180 "workflow much more fluid and efficient."
230 "Header bar"
181 231 ]
182 232 },
183 233 {
184 234 "cell_type": "markdown",
235 "metadata": {},
185 236 "source": [
186 "### Header bar",
187 "",
188 "The header area at the top allows you to rename an existing ",
189 "notebook and open up a short help tooltip. This area also indicates",
190 "with a red **Busy** mark on the right whenever the kernel is busy executing",
237 "The header area at the top allows you to rename an existing \n",
238 "notebook and open up a short help tooltip. This area also indicates\n",
239 "with a red **Busy** mark on the right whenever the kernel is busy executing\n",
191 240 "code."
192 241 ]
193 242 },
194 243 {
244 "cell_type": "heading",
245 "level": 3,
246 "metadata": {},
247 "source": [
248 "The pager at the bottom"
249 ]
250 },
251 {
195 252 "cell_type": "markdown",
253 "metadata": {},
196 254 "source": [
197 "### The pager at the bottom",
198 "",
199 "Whenever IPython needs to display additional ",
200 "information, such as when you type `somefunction?` in a cell, the notebook",
201 "opens a pane at the bottom where this information is shown. You can keep",
202 "this pager pane open for reference (it doesn't block input in the main area)",
255 "Whenever IPython needs to display additional \n",
256 "information, such as when you type `somefunction?` in a cell, the notebook\n",
257 "opens a pane at the bottom where this information is shown. You can keep\n",
258 "this pager pane open for reference (it doesn't block input in the main area)\n",
203 259 "or dismiss it by clicking on its divider bar."
204 260 ]
205 261 },
206 262 {
263 "cell_type": "heading",
264 "level": 3,
265 "metadata": {},
266 "source": [
267 "Tab completion and tooltips"
268 ]
269 },
270 {
207 271 "cell_type": "markdown",
272 "metadata": {},
208 273 "source": [
209 "### Tab completion and tooltips",
210 "",
211 "The notebook uses the same underlying machinery for tab completion that ",
212 "IPython uses at the terminal, but displays the information differently.",
213 "Whey you complete with the `Tab` key, IPython shows a drop list with all",
214 "available completions. If you type more characters while this list is open,",
215 "IPython automatically eliminates from the list options that don't match the",
216 "new characters; once there is only one option left you can hit `Tab` once",
217 "more (or `Enter`) to complete. You can also select the completion you",
218 "want with the arrow keys or the mouse, and then hit `Enter`.",
219 "",
220 "In addition, if you hit `Tab` inside of open parentheses, IPython will ",
221 "search for the docstring of the last object left of the parens and will",
222 "display it on a tooltip. For example, type `list(<TAB>` and you will",
274 "The notebook uses the same underlying machinery for tab completion that \n",
275 "IPython uses at the terminal, but displays the information differently.\n",
276 "Whey you complete with the `Tab` key, IPython shows a drop list with all\n",
277 "available completions. If you type more characters while this list is open,\n",
278 "IPython automatically eliminates from the list options that don't match the\n",
279 "new characters; once there is only one option left you can hit `Tab` once\n",
280 "more (or `Enter`) to complete. You can also select the completion you\n",
281 "want with the arrow keys or the mouse, and then hit `Enter`.\n",
282 "\n",
283 "In addition, if you hit `Tab` inside of open parentheses, IPython will \n",
284 "search for the docstring of the last object left of the parens and will\n",
285 "display it on a tooltip. For example, type `list(<TAB>` and you will\n",
223 286 "see the docstring for the builtin `list` constructor:"
224 287 ]
225 288 },
226 289 {
227 290 "cell_type": "code",
291 "collapsed": false,
228 292 "input": [
229 "# Position your cursor after the ( and hit the Tab key:",
293 "# Position your cursor after the ( and hit the Tab key:\n",
230 294 "range("
231 295 ],
232 296 "language": "python",
297 "metadata": {},
233 298 "outputs": []
234 299 },
235 300 {
236 301 "cell_type": "markdown",
302 "metadata": {},
237 303 "source": [
238 "More over pressing tab several time in a row allows you change the behaviour of the tooltip.",
239 "",
240 "* firt `tab` press, you get a classical tooltip",
241 "* second time, the tooltip grow vertically, and allow you to scroll the docstring",
242 "* third tab press, tooltip, will be made sticky for 10 seconds, allowing you to carry on typing while it stays open.",
243 "* forth time press, the tooltip help is sent to the pager at the bottom of the screen , and is dismiss.",
244 "<script>",
245 " IPython.tooltip.tabs_functions = [ function(cell,text){",
246 " IPython.tooltip._request_tooltip(cell,text);",
247 " IPython.notification_widget.set_message('tab again to expand pager',2500);",
248 " setTimeout(function(){",
249 " $('.tooltiptext pre').text(\"function signture : You've invoked a tooltip !\\n\\nWell done! Here usualy lies the current function *call signature* and it's *docstring*. You can now expand the tooltip pressing <tab> a second time...\")},400);",
250 " },",
251 " function(){",
252 " IPython.tooltip.expand();",
253 " IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500);",
254 " setTimeout(function(){",
255 " $('.tooltiptext pre').text(\"Now the tooltip is expanded !\\",
256 " \\n\\nThis is really usefull if you have long docstring and if you want to be able to scroll them. \\",
257 "For example, I can give you many information about the tooltip:\\n - The tooltip is smart, and \\",
258 "you don't always need to press tab to invoke it, if you press an opening bracket `(` then nothing \\",
259 "for some time, tooltip will be invoked by itself.\\",
260 "\\n - Also you can hoover over the icon on the top right to know what they are dooing...\\",
261 "\\n\\nBack to the next lesson.\\n\\nSometime you need to the tooltip to stay on screen while\\",
262 "you type. That's the reason for the sticky mode (indicated by a small clock on the top left of the tooltip),\\",
263 "\\n\\nNow press <tab> a 3rd time and continue typing some text to test it...\")",
264 " },400);",
265 " },",
266 " function(){",
267 " var time = 35;",
268 " IPython.tooltip.stick(time);",
269 " $('.tooltiptext pre').text(\"Type more text !...\\n\\n range(7,125,3)\\n\\n The tooltip is in sticky mode, it won't be dismissed for at least 10 secondes \",400);",
270 " setTimeout(function(){",
271 " $('.tooltiptext pre').text(\"That was sticky mode...\\nI'll keep it on 15 more seconds just for you.\\n\\nLast thing you can do is send the current help displayed in the tooltip to the pager at the bottom of the screen. To do that, press tab 4 time in a row after a parenthesis. \\n\\n Now I'll stop bothering you and let you Play with the tooltip !\");",
272 " reset_tooltip()",
273 " },15000);",
274 " },",
275 " function(cell){",
276 " IPython.tooltip.cancel_stick();",
277 " reset_tooltip()",
278 " IPython.tooltip.showInPager(cell);",
279 " IPython.tooltip._cmfocus();",
280 " }",
281 " ];",
282 " ",
283 " reset_tooltip = function(){",
284 " IPython.tooltip.tabs_functions = [ function(cell,text){",
285 " IPython.tooltip._request_tooltip(cell,text);",
286 " IPython.notification_widget.set_message('tab again to expand pager',2500);",
287 " },",
288 " function(){",
289 " IPython.tooltip.expand();",
290 " IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500);",
291 " },",
292 " function(){",
293 " IPython.tooltip.stick();",
294 " IPython.notification_widget.set_message('tab again to open help in pager',2500);",
295 " },",
296 " function(cell){",
297 " IPython.tooltip.cancel_stick();",
298 " IPython.tooltip.showInPager(cell);",
299 " IPython.tooltip._cmfocus();",
300 " }",
301 " ];",
302 " }",
304 "Moreover, pressing tab several time in a row allows you change the behaviour of the tooltip.\n",
305 "\n",
306 "* first `tab` press, you get a classical tooltip\n",
307 "* second tab, the tooltip grow vertically, and allow you to scroll the docstring\n",
308 "* third tab, tooltip will be made sticky for 10 seconds, allowing you to carry on typing while it stays open.\n",
309 "* forth tab, the tooltip help is sent to the pager at the bottom of the screen.\n",
310 "<script>\n",
311 " IPython.tooltip.tabs_functions = [ function(cell,text){\n",
312 " IPython.tooltip._request_tooltip(cell,text);\n",
313 " IPython.notification_widget.set_message('tab again to expand pager',2500);\n",
314 " setTimeout(function(){\n",
315 " $('.tooltiptext pre').text(\"function signture : You've invoked a tooltip !\\n\\nWell done! Here usualy lies the current function *call signature* and it's *docstring*. You can now expand the tooltip pressing <tab> a second time...\")},400);\n",
316 " },\n",
317 " function(){\n",
318 " IPython.tooltip.expand();\n",
319 " IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500);\n",
320 " setTimeout(function(){\n",
321 " $('.tooltiptext pre').text(\"Now the tooltip is expanded !\\\n",
322 " \\n\\nThis is really usefull if you have long docstring and if you want to be able to scroll them. \\\n",
323 "For example, I can give you many information about the tooltip:\\n - The tooltip is smart, and \\\n",
324 "you don't always need to press tab to invoke it, if you press an opening bracket `(` then nothing \\\n",
325 "for some time, tooltip will be invoked by itself.\\\n",
326 "\\n - Also you can hoover over the icon on the top right to know what they are dooing...\\\n",
327 "\\n\\nBack to the next lesson.\\n\\nSometime you need to the tooltip to stay on screen while\\\n",
328 "you type. That's the reason for the sticky mode (indicated by a small clock on the top left of the tooltip),\\\n",
329 "\\n\\nNow press <tab> a 3rd time and continue typing some text to test it...\")\n",
330 " },400);\n",
331 " },\n",
332 " function(){\n",
333 " var time = 35;\n",
334 " IPython.tooltip.stick(time);\n",
335 " $('.tooltiptext pre').text(\"Type more text !...\\n\\n range(7,125,3)\\n\\n The tooltip is in sticky mode, it won't be dismissed for at least 10 secondes \",400);\n",
336 " setTimeout(function(){\n",
337 " $('.tooltiptext pre').text(\"That was sticky mode...\\nI'll keep it on 15 more seconds just for you.\\n\\nLast thing you can do is send the current help displayed in the tooltip to the pager at the bottom of the screen. To do that, press tab 4 time in a row after a parenthesis. \\n\\n Now I'll stop bothering you and let you Play with the tooltip !\");\n",
338 " reset_tooltip()\n",
339 " },15000);\n",
340 " },\n",
341 " function(cell){\n",
342 " IPython.tooltip.cancel_stick();\n",
343 " reset_tooltip()\n",
344 " IPython.tooltip.showInPager(cell);\n",
345 " IPython.tooltip._cmfocus();\n",
346 " }\n",
347 " ];\n",
348 " \n",
349 " reset_tooltip = function(){\n",
350 " IPython.tooltip.tabs_functions = [ function(cell,text){\n",
351 " IPython.tooltip._request_tooltip(cell,text);\n",
352 " IPython.notification_widget.set_message('tab again to expand pager',2500);\n",
353 " },\n",
354 " function(){\n",
355 " IPython.tooltip.expand();\n",
356 " IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500);\n",
357 " },\n",
358 " function(){\n",
359 " IPython.tooltip.stick();\n",
360 " IPython.notification_widget.set_message('tab again to open help in pager',2500);\n",
361 " },\n",
362 " function(cell){\n",
363 " IPython.tooltip.cancel_stick();\n",
364 " IPython.tooltip.showInPager(cell);\n",
365 " IPython.tooltip._cmfocus();\n",
366 " }\n",
367 " ];\n",
368 " }\n",
303 369 "</script>"
304 370 ]
305 371 },
306 372 {
373 "cell_type": "heading",
374 "level": 2,
375 "metadata": {},
376 "source": [
377 "The frontend/kernel model"
378 ]
379 },
380 {
307 381 "cell_type": "markdown",
382 "metadata": {},
308 383 "source": [
309 "## The frontend/kernel model",
310 "",
311 "The IPython notebook works on a client/server model where an *IPython kernel*",
312 "starts in a separate process and acts as a server to executes the code you type,",
313 "while the web browser provides acts as a client, providing a front end environment",
314 "for you to type. But one kernel is capable of simultaneously talking to more than",
315 "one client, and they do not all need to be of the same kind. All IPython frontends",
316 "are capable of communicating with a kernel, and any number of them can be active",
317 "at the same time. In addition to allowing you to have, for example, more than one",
318 "browser session active, this lets you connect clients with different user interface features.",
319 "",
320 "For example, you may want to connect a Qt console to your kernel and use it as a help",
321 "browser, calling `??` on objects in the Qt console (whose pager is more flexible than the",
322 "one in the notebook). You can start a new Qt console connected to your current kernel by ",
323 "using the `%qtconsole` magic, this will automatically detect the necessary connection",
324 "information.",
325 "",
326 "If you want to open one manually, or want to open a text console from a terminal, you can ",
384 "The IPython notebook works on a client/server model where an *IPython kernel*\n",
385 "starts in a separate process and acts as a server to executes the code you type,\n",
386 "while the web browser provides acts as a client, providing a front end environment\n",
387 "for you to type. But one kernel is capable of simultaneously talking to more than\n",
388 "one client, and they do not all need to be of the same kind. All IPython frontends\n",
389 "are capable of communicating with a kernel, and any number of them can be active\n",
390 "at the same time. In addition to allowing you to have, for example, more than one\n",
391 "browser session active, this lets you connect clients with different user interface features.\n",
392 "\n",
393 "For example, you may want to connect a Qt console to your kernel and use it as a help\n",
394 "browser, calling `??` on objects in the Qt console (whose pager is more flexible than the\n",
395 "one in the notebook). You can start a new Qt console connected to your current kernel by \n",
396 "using the `%qtconsole` magic, this will automatically detect the necessary connection\n",
397 "information.\n",
398 "\n",
399 "If you want to open one manually, or want to open a text console from a terminal, you can \n",
327 400 "get your kernel's connection information with the `%connect_info` magic:"
328 401 ]
329 402 },
330 403 {
331 404 "cell_type": "code",
405 "collapsed": false,
332 406 "input": [
333 407 "%connect_info"
334 408 ],
335 409 "language": "python",
410 "metadata": {},
336 411 "outputs": [
337 412 {
338 413 "output_type": "stream",
339 414 "stream": "stdout",
340 415 "text": [
341 "{",
342 " \"stdin_port\": 53970, ",
343 " \"ip\": \"127.0.0.1\", ",
344 " \"hb_port\": 53971, ",
345 " \"key\": \"30daac61-6b73-4bae-a7d9-9dca538794d5\", ",
346 " \"shell_port\": 53968, ",
347 " \"iopub_port\": 53969",
348 "}",
349 "",
350 "Paste the above JSON into a file, and connect with:",
351 " $> ipython <app> --existing <file>",
352 "or, if you are local, you can connect with just:",
353 " $> ipython <app> --existing kernel-dd85d1cc-c335-44f4-bed8-f1a2173a819a.json ",
354 "or even just:",
355 " $> ipython <app> --existing ",
356 "if this is the most recent IPython session you have started."
416 "{\n",
417 " \"stdin_port\": 52858, \n",
418 " \"ip\": \"127.0.0.1\", \n",
419 " \"hb_port\": 52859, \n",
420 " \"key\": \"7efd45ca-d8a2-41b0-9cea-d9116d0fb883\", \n",
421 " \"shell_port\": 52856, \n",
422 " \"iopub_port\": 52857\n",
423 "}\n",
424 "\n",
425 "Paste the above JSON into a file, and connect with:\n",
426 " $> ipython <app> --existing <file>\n",
427 "or, if you are local, you can connect with just:\n",
428 " $> ipython <app> --existing kernel-b3bac7c1-8b2c-4536-8082-8d1df24f99ac.json \n",
429 "or even just:\n",
430 " $> ipython <app> --existing \n",
431 "if this is the most recent IPython session you have started.\n"
357 432 ]
358 433 }
359 434 ],
360 "prompt_number": 4
435 "prompt_number": 6
436 },
437 {
438 "cell_type": "heading",
439 "level": 2,
440 "metadata": {},
441 "source": [
442 "The kernel's `raw_input` and `%debug`"
443 ]
361 444 },
362 445 {
363 446 "cell_type": "markdown",
447 "metadata": {},
364 448 "source": [
365 "## The kernel's `raw_input` and `%debug`",
366 "",
367 "The one feature the notebook currently doesn't support as a client is the ability to send data to the kernel's",
368 "standard input socket. That is, if the kernel requires information to be typed interactively by calling the",
369 "builtin `raw_input` function, the notebook will be blocked. This happens for example if you run a script",
370 "that queries interactively for parameters, and very importantly, is how the interactive IPython debugger that ",
371 "activates when you type `%debug` works.",
372 "",
373 "So, in order to be able to use `%debug` or anything else that requires `raw_input`, you can either use a Qt ",
374 "console or a terminal console:",
375 "",
376 "- From the notebook, typing `%qtconsole` finds all the necessary connection data for you.",
377 "- From the terminal, first type `%connect_info` while still in the notebook, and then copy and paste the ",
449 "The one feature the notebook currently doesn't support as a client is the ability to send data to the kernel's\n",
450 "standard input socket. That is, if the kernel requires information to be typed interactively by calling the\n",
451 "builtin `raw_input` function, the notebook will be blocked. This happens for example if you run a script\n",
452 "that queries interactively for parameters, and very importantly, is how the interactive IPython debugger that \n",
453 "activates when you type `%debug` works.\n",
454 "\n",
455 "So, in order to be able to use `%debug` or anything else that requires `raw_input`, you can either use a Qt \n",
456 "console or a terminal console:\n",
457 "\n",
458 "- From the notebook, typing `%qtconsole` finds all the necessary connection data for you.\n",
459 "- From the terminal, first type `%connect_info` while still in the notebook, and then copy and paste the \n",
378 460 "resulting information, using `qtconsole` or `console` depending on which type of client you want."
379 461 ]
380 462 },
381 463 {
464 "cell_type": "heading",
465 "level": 2,
466 "metadata": {},
467 "source": [
468 "Display of complex objects"
469 ]
470 },
471 {
382 472 "cell_type": "markdown",
473 "metadata": {},
383 474 "source": [
384 "## Display of complex objects",
385 "",
386 "As the 'tour' notebook shows, the IPython notebook has fairly sophisticated display capabilities. In addition",
387 "to the examples there, you can study the `display_protocol` notebook in this same examples folder, to ",
388 "learn how to customize arbitrary objects (in your own code or external libraries) to display in the notebook",
475 "As the 'tour' notebook shows, the IPython notebook has fairly sophisticated display capabilities. In addition\n",
476 "to the examples there, you can study the `display_protocol` notebook in this same examples folder, to \n",
477 "learn how to customize arbitrary objects (in your own code or external libraries) to display in the notebook\n",
389 478 "in any way you want, including graphical forms or mathematical expressions."
390 479 ]
391 480 },
392 481 {
482 "cell_type": "heading",
483 "level": 2,
484 "metadata": {},
485 "source": [
486 "Plotting support"
487 ]
488 },
489 {
393 490 "cell_type": "markdown",
491 "metadata": {},
394 492 "source": [
395 "## Plotting support",
396 "",
397 "As we've explained already, the notebook is just another frontend talking to the same IPython kernel that",
398 "you're already familiar with, so the same options for plotting support apply.",
399 "",
400 "If you start the notebook with `--pylab`, you will get matplotlib's floating, interactive windows and you",
401 "can call the `display` function to paste figures into the notebook document. If you start it with ",
402 "`--pylab inline`, all plots will appear inline automatically. In this regard, the notebook works identically",
403 "to the Qt console.",
404 "",
405 "Note that if you start the notebook server with pylab support, *all* kernels are automatically started in",
406 "pylab mode and with the same choice of backend (i.e. floating windows or inline figures). But you can also",
407 "start the notebook server simply by typing `ipython notebook`, and then selectively turn on pylab support ",
408 "only for the notebooks you want by using the `%pylab` magic (see its docstring for details)."
493 "As we've explained already, the notebook is just another frontend talking to the same IPython kernel that\n",
494 "you're familiar with, so the same options for plotting support apply.\n",
495 "\n",
496 "You can enable inline plotting with `%pylab inline`:"
409 497 ]
410 498 },
411 499 {
412 500 "cell_type": "code",
501 "collapsed": false,
413 502 "input": [
414 "%pylab inline",
415 "plot(rand(100))"
503 "%pylab inline"
416 504 ],
417 505 "language": "python",
506 "metadata": {},
418 507 "outputs": [
419 508 {
420 509 "output_type": "stream",
421 510 "stream": "stdout",
422 511 "text": [
423 "",
424 "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].",
425 "For more information, type 'help(pylab)'."
512 "\n",
513 "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].\n",
514 "For more information, type 'help(pylab)'.\n"
426 515 ]
427 },
516 }
517 ],
518 "prompt_number": 7
519 },
520 {
521 "cell_type": "markdown",
522 "metadata": {},
523 "source": [
524 "If you start the notebook server itself with `--pylab`, you will get matplotlib's floating, interactive windows and you\n",
525 "can call the `display` function to paste figures into the notebook document. If you start it with \n",
526 "`--pylab inline`, all plots will appear inline automatically. In this regard, the notebook works identically\n",
527 "to the Qt console.\n",
528 "\n",
529 "Note that if you start the notebook server with pylab support, *all* kernels are automatically started in\n",
530 "pylab mode and with the same choice of backend (i.e. floating windows or inline figures).\n",
531 "For this reason, it is recommended that you\n",
532 "start the notebook server simply by typing `ipython notebook`, and then selectively turn on pylab support \n",
533 "only for the notebooks you want by using the `%pylab` magic (see its docstring for details)."
534 ]
535 },
536 {
537 "cell_type": "code",
538 "collapsed": false,
539 "input": [
540 "plot(rand(100))"
541 ],
542 "language": "python",
543 "metadata": {},
544 "outputs": [
428 545 {
429 546 "output_type": "pyout",
430 "prompt_number": 5,
547 "prompt_number": 8,
431 548 "text": [
432 "[<matplotlib.lines.Line2D at 0x11165bcd0>]"
549 "[<matplotlib.lines.Line2D at 0x1124ba350>]"
433 550 ]
434 551 },
435 552 {
436 553 "output_type": "display_data",
437 "png": "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\n"
554 "png": "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\nDVi7dm3cTUgMSqkvvv/9cPdfSn0RNmxfBIeS4OfMmYPOzs5Tnzs7O9HISRh+m66uLswRSAD+IWBh\nYWFhES6UFs3SpUuxe/dudHR0YHh4GJs3b8aqVasKtlm1ahXuu+8+AMC2bdswadIkzJw5M7wWW1hY\nWFhoQangs9ksNmzYgBUrVmB0dBTXXXcdFixYgI0bNwIA1qxZg8suuwyPPfYYmpubUV9fj3vuuSeS\nhltYWFhYuMAJGY8//rgzf/58p7m52bntttvCPlyi8P777zvLly93Fi5c6Jx11lnOnXfe6TiO4xw+\nfNi5+OKLnZaWFueSSy5xjh49GnNLo8PIyIizZMkS57Of/azjOOnti6NHjzpXXnml09ra6ixYsMDZ\ntm1bavti3bp1zsKFC51FixY511xzjTM4OJiavrj22mudGTNmOIsWLTr1nerc161b5zQ3Nzvz5893\nfve737nuP9R5ajp59OWMqqoq3HHHHXjjjTewbds2/PjHP8auXbtw22234ZJLLsHbb7+Niy66CLfd\ndlvcTY0Md955JxYuXHgq4J7WvvjGN76Byy67DLt27cJrr72G1tbWVPZFR0cHfvrTn2LHjh14/fXX\nMTo6ivvvvz81fXHttdeira2t4DvZue/cuRObN2/Gzp070dbWhq997WsYGxtTHyCUx9IHeO6555wV\nK1ac+vz973/f+f73vx/mIRONyy+/3HniiSec+fPnO/v373ccx3H27dvnzJ8/P+aWRYPOzk7noosu\ncv74xz+eUvBp7Ive3l7njDPOKPo+jX1x+PBhZ968ec6RI0ecXC7nfPazn3V+//vfp6ov9uzZU6Dg\nZee+bt26AhdkxYoVzp///GflvkNV8Dp59GlBR0cHXn75ZSxbtgwHDhw4FYieOXNmaiaGffOb38QP\nfvADVDAFTtLYF3v27MH06dNx7bXX4qMf/Siuv/56nDhxIpV9MWXKFNxyyy04/fTT0dDQgEmTJuGS\nSy5JZV9QyM597969BVmMOnwaKsHbvHeC/v5+XHnllbjzzjsxfvz4gv/LZDKp6KdHH30UM2bMwDnn\nnCNNmU1LX4yMjGDHjh342te+hh07dqC+vr7IgkhLX7z77rv44Q9/iI6ODuzduxf9/f345S9/WbBN\nWvpCBLdzd+uXUAleJ4++3JHL5XDllVfii1/8Ij7/+c8DIE/l/fv3AwD27duHGSlYbv65557Dww8/\njDPOOAPXXHMN/vjHP+KLX/xiKvuisbERjY2NOPfccwEAV111FXbs2IFZs2alri9efPFFfPzjH8fU\nqVORzWZxxRVX4M9//nMq+4JCdk/ozjliESrB6+TRlzMcx8F1112HhQsX4uabbz71/apVq3DvvfcC\nAO69995TxF/OWLduHTo7O7Fnzx7cf//9uPDCC/GLX/wilX0xa9YsNDU14e233wYAbN26FWeddRY+\n97nPpa4vWltbsW3bNgwMDMBxHGzduhULFy5MZV9QyO6JVatW4f7778fw8DD27NmD3bt347zzzlPv\nzHTAgMdjjz3mzJs3zznzzDOddevWhX24ROGZZ55xMpmMs3jxYmfJkiXOkiVLnMcff9w5fPiwc9FF\nF5V9CpgM7e3tzuc+9znHcZzU9sUrr7ziLF261Dn77LOdL3zhC05vb29q+2L9+vWn0iS/9KUvOcPD\nw6npi9WrVzuzZ892qqqqnMbGRudnP/uZ8ty/973vOWeeeaYzf/58p62tzXX/GcexNQQsLCwsyhF2\nvRYLCwuLMoUleAsLC4syhSV4CwsLizKFJXgLCwuLMoUleAsLC4syhSV4CwsLizLF/weSDoopnVla\nxAAAAABJRU5ErkJggg==\n"
438 555 }
439 556 ],
440 "prompt_number": 5
557 "prompt_number": 8
441 558 },
442 559 {
443 "cell_type": "markdown",
560 "cell_type": "heading",
561 "level": 2,
562 "metadata": {},
444 563 "source": [
445 "## Security",
446 "",
447 "By default the notebook only listens on localhost, so it does not expose your computer to attacks coming from",
448 "the internet. By default the notebook does not require any authentication, but you can configure it to",
449 "ask for a password before allowing access to the files. ",
450 "",
451 "Furthermore, you can require the notebook to encrypt all communications by using SSL and making all connections",
452 "using the https protocol instead of plain http. This is a good idea if you decide to run your notebook on",
453 "addresses that are visible from the internet. For further details on how to configure this, see the",
454 "[security section](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html#security) of the ",
455 "manual.",
456 "",
457 "Finally, note that you can also run a notebook with the `--read-only` flag, which lets you provide access",
458 "to your notebook documents to others without letting them execute code (which can be useful to broadcast",
459 "a computation to colleagues or students, for example). The read-only flag behaves differently depending",
460 "on whether the server has a password or not:",
461 "",
462 "- Passwordless server: users directly see all notebooks in read-only mode.",
463 "- Password-protected server: users can see all notebooks in read-only mode, but a login button is available",
464 "and once a user authenticates, he or she obtains write/execute privileges.",
465 "",
466 "The first case above makes it easy to broadcast on the fly an existing notebook by simply starting a *second* ",
467 "notebook server in the same directory as the first, but in read-only mode. This can be done without having",
468 "to configure a password first (which requires calling a hashing function and editing a configuration file)."
564 "Security"
469 565 ]
470 566 },
471 567 {
472 "cell_type": "code",
473 "input": [
474 ""
475 ],
476 "language": "python",
477 "outputs": []
568 "cell_type": "markdown",
569 "metadata": {},
570 "source": [
571 "By default the notebook only listens on localhost, so it does not expose your computer to attacks coming from\n",
572 "the internet. By default the notebook does not require any authentication, but you can configure it to\n",
573 "ask for a password before allowing access to the files. \n",
574 "\n",
575 "Furthermore, you can require the notebook to encrypt all communications by using SSL and making all connections\n",
576 "using the https protocol instead of plain http. This is a good idea if you decide to run your notebook on\n",
577 "addresses that are visible from the internet. For further details on how to configure this, see the\n",
578 "[security section](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html#security) of the \n",
579 "manual.\n",
580 "\n",
581 "Finally, note that you can also run a notebook with the `--read-only` flag, which lets you provide access\n",
582 "to your notebook documents to others without letting them execute code (which can be useful to broadcast\n",
583 "a computation to colleagues or students, for example). The read-only flag behaves differently depending\n",
584 "on whether the server has a password or not:\n",
585 "\n",
586 "- Passwordless server: users directly see all notebooks in read-only mode.\n",
587 "- Password-protected server: users can see all notebooks in read-only mode, but a login button is available\n",
588 "and once a user authenticates, he or she obtains write/execute privileges.\n",
589 "\n",
590 "The first case above makes it easy to broadcast on the fly an existing notebook by simply starting a *second* \n",
591 "notebook server in the same directory as the first, but in read-only mode. This can be done without having\n",
592 "to configure a password first (which requires calling a hashing function and editing a configuration file).\n",
593 "\n",
594 "**NOTE:** IPython 0.13's javascript rewrite did not include read-only UI, so it does not work well.\n",
595 "Code/notebooks are still protected from unauthorized access, but the UI is not appropriately restricted."
596 ]
478 597 }
479 ]
598 ],
599 "metadata": {}
480 600 }
481 601 ]
482 602 } No newline at end of file
@@ -3,30 +3,34 b''
3 3 "name": "Animations_and_Progress"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "heading",
11 12 "level": 1,
13 "metadata": {},
12 14 "source": [
13 15 "Simple animations, progress bars, and clearing output"
14 16 ]
15 17 },
16 18 {
17 19 "cell_type": "markdown",
20 "metadata": {},
18 21 "source": [
19 "Sometimes you want to print progress in-place, but don't want",
20 "to keep growing the output area. In terminals, there is the carriage-return",
21 "(`'\\r'`) for overwriting a single line, but the notebook frontend does not support this",
22 "behavior (yet).",
23 "",
24 "What the notebook *does* support is explicit `clear_output`, and you can use this to replace previous",
22 "Sometimes you want to print progress in-place, but don't want\n",
23 "to keep growing the output area. In terminals, there is the carriage-return\n",
24 "(`'\\r'`) for overwriting a single line, but the notebook frontend does not support this\n",
25 "behavior (yet).\n",
26 "\n",
27 "What the notebook *does* support is explicit `clear_output`, and you can use this to replace previous\n",
25 28 "output (specifying stdout/stderr or the special IPython display outputs)."
26 29 ]
27 30 },
28 31 {
29 32 "cell_type": "markdown",
33 "metadata": {},
30 34 "source": [
31 35 "A simple example printing our progress iterating through a list:"
32 36 ]
@@ -35,34 +39,35 b''
35 39 "cell_type": "code",
36 40 "collapsed": true,
37 41 "input": [
38 "import sys",
42 "import sys\n",
39 43 "import time"
40 44 ],
41 45 "language": "python",
42 "outputs": [],
43 "prompt_number": 16
46 "metadata": {},
47 "outputs": []
44 48 },
45 49 {
46 50 "cell_type": "code",
47 51 "collapsed": false,
48 52 "input": [
49 "from IPython.core.display import clear_output",
50 "for i in range(10):",
51 " time.sleep(0.25)",
52 " clear_output()",
53 " print i",
53 "from IPython.core.display import clear_output\n",
54 "for i in range(10):\n",
55 " time.sleep(0.25)\n",
56 " clear_output()\n",
57 " print i\n",
54 58 " sys.stdout.flush()"
55 59 ],
56 60 "language": "python",
57 "outputs": [],
58 "prompt_number": 12
61 "metadata": {},
62 "outputs": []
59 63 },
60 64 {
61 65 "cell_type": "markdown",
66 "metadata": {},
62 67 "source": [
63 "The AsyncResult object has a special `wait_interactive()` method, which prints its progress interactively,",
64 "so you can watch as your parallel computation completes.",
65 "",
68 "The AsyncResult object has a special `wait_interactive()` method, which prints its progress interactively,\n",
69 "so you can watch as your parallel computation completes.\n",
70 "\n",
66 71 "**This example assumes you have an IPython cluster running, which you can start from the [cluster panel](/#tab2)**"
67 72 ]
68 73 },
@@ -70,23 +75,24 b''
70 75 "cell_type": "code",
71 76 "collapsed": false,
72 77 "input": [
73 "from IPython import parallel",
74 "rc = parallel.Client()",
75 "view = rc.load_balanced_view()",
76 "",
77 "amr = view.map_async(time.sleep, [0.5]*100)",
78 "",
78 "from IPython import parallel\n",
79 "rc = parallel.Client()\n",
80 "view = rc.load_balanced_view()\n",
81 "\n",
82 "amr = view.map_async(time.sleep, [0.5]*100)\n",
83 "\n",
79 84 "amr.wait_interactive()"
80 85 ],
81 86 "language": "python",
82 "outputs": [],
83 "prompt_number": 13
87 "metadata": {},
88 "outputs": []
84 89 },
85 90 {
86 91 "cell_type": "markdown",
92 "metadata": {},
87 93 "source": [
88 "You can also use `clear_output()` to clear figures and plots.",
89 "",
94 "You can also use `clear_output()` to clear figures and plots.\n",
95 "\n",
90 96 "This time, we need to make sure we are using inline pylab (**requires matplotlib**)"
91 97 ]
92 98 },
@@ -97,63 +103,47 b''
97 103 "%pylab inline"
98 104 ],
99 105 "language": "python",
100 "outputs": [
101 {
102 "output_type": "stream",
103 "stream": "stdout",
104 "text": [
105 "",
106 "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].",
107 "For more information, type 'help(pylab)'."
108 ]
109 }
110 ],
111 "prompt_number": 17
106 "metadata": {},
107 "outputs": []
112 108 },
113 109 {
114 110 "cell_type": "code",
115 111 "collapsed": false,
116 112 "input": [
117 "from scipy.special import jn",
118 "x = np.linspace(0,5)",
119 "f, ax = plt.subplots()",
120 "ax.set_title(\"Bessel functions\")",
121 "",
122 "for n in range(1,10):",
123 " time.sleep(1)",
124 " ax.plot(x, jn(x,n))",
125 " clear_output()",
126 " display(f)",
127 "",
128 "# close the figure at the end, so we don't get a duplicate",
129 "# of the last plot",
113 "from scipy.special import jn\n",
114 "x = np.linspace(0,5)\n",
115 "f, ax = plt.subplots()\n",
116 "ax.set_title(\"Bessel functions\")\n",
117 "\n",
118 "for n in range(1,10):\n",
119 " time.sleep(1)\n",
120 " ax.plot(x, jn(x,n))\n",
121 " clear_output()\n",
122 " display(f)\n",
123 "\n",
124 "# close the figure at the end, so we don't get a duplicate\n",
125 "# of the last plot\n",
130 126 "plt.close()"
131 127 ],
132 128 "language": "python",
133 "outputs": [
134 {
135 "output_type": "display_data",
136 "png": "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\nYII=\n",
137 "text": [
138 "<matplotlib.figure.Figure at 0x1083272d0>"
139 ]
140 }
141 ],
142 "prompt_number": 20
129 "metadata": {},
130 "outputs": []
143 131 },
144 132 {
145 133 "cell_type": "heading",
146 134 "level": 2,
135 "metadata": {},
147 136 "source": [
148 137 "A Javascript Progress Bar"
149 138 ]
150 139 },
151 140 {
152 141 "cell_type": "markdown",
142 "metadata": {},
153 143 "source": [
154 "`clear_output()` is still something of a hack, and if you want to do a progress bar in the notebook",
155 "it is better to just use Javascript/HTML if you can.",
156 "",
144 "`clear_output()` is still something of a hack, and if you want to do a progress bar in the notebook\n",
145 "it is better to just use Javascript/HTML if you can.\n",
146 "\n",
157 147 "Here is a simple progress bar using HTML/Javascript:"
158 148 ]
159 149 },
@@ -161,47 +151,50 b''
161 151 "cell_type": "code",
162 152 "collapsed": false,
163 153 "input": [
164 "import uuid",
165 "from IPython.core.display import HTML, Javascript, display",
166 "",
167 "divid = str(uuid.uuid4())",
168 "",
169 "pb = HTML(",
170 "\"\"\"",
171 "<div style=\"border: 1px solid black; width:500px\">",
172 " <div id=\"%s\" style=\"background-color:blue; width:0%%\">&nbsp;</div>",
173 "</div> ",
174 "\"\"\" % divid)",
175 "display(pb)",
176 "for i in range(1,101):",
177 " time.sleep(0.1)",
178 " ",
154 "import uuid\n",
155 "from IPython.core.display import HTML, Javascript, display\n",
156 "\n",
157 "divid = str(uuid.uuid4())\n",
158 "\n",
159 "pb = HTML(\n",
160 "\"\"\"\n",
161 "<div style=\"border: 1px solid black; width:500px\">\n",
162 " <div id=\"%s\" style=\"background-color:blue; width:0%%\">&nbsp;</div>\n",
163 "</div> \n",
164 "\"\"\" % divid)\n",
165 "display(pb)\n",
166 "for i in range(1,101):\n",
167 " time.sleep(0.1)\n",
168 " \n",
179 169 " display(Javascript(\"$('div#%s').width('%i%%')\" % (divid, i)))"
180 170 ],
181 171 "language": "python",
182 "outputs": [],
183 "prompt_number": 15
172 "metadata": {},
173 "outputs": []
184 174 },
185 175 {
186 176 "cell_type": "markdown",
177 "metadata": {},
187 178 "source": [
188 "The above simply makes a div that is a box, and a blue div inside it with a unique ID ",
189 "(so that the javascript won't collide with other similar progress bars on the same page). ",
190 "",
191 "Then, at every progress point, we run a simple jQuery call to resize the blue box to",
192 "the appropriate fraction of the width of its containing box, and voil\u00e0 a nice",
179 "The above simply makes a div that is a box, and a blue div inside it with a unique ID \n",
180 "(so that the javascript won't collide with other similar progress bars on the same page). \n",
181 "\n",
182 "Then, at every progress point, we run a simple jQuery call to resize the blue box to\n",
183 "the appropriate fraction of the width of its containing box, and voil\u00e0 a nice\n",
193 184 "HTML/Javascript progress bar!"
194 185 ]
195 186 },
196 187 {
197 188 "cell_type": "heading",
198 189 "level": 2,
190 "metadata": {},
199 191 "source": [
200 192 "ProgressBar class"
201 193 ]
202 194 },
203 195 {
204 196 "cell_type": "markdown",
197 "metadata": {},
205 198 "source": [
206 199 "And finally, here is a progress bar *class* extracted from [PyMC](http://code.google.com/p/pymc/), which will work in regular Python as well as in the IPython Notebook"
207 200 ]
@@ -210,65 +203,73 b''
210 203 "cell_type": "code",
211 204 "collapsed": true,
212 205 "input": [
213 "import sys, time",
214 "try:",
215 " from IPython.core.display import clear_output",
216 " have_ipython = True",
217 "except ImportError:",
218 " have_ipython = False",
219 "",
220 "class ProgressBar:",
221 " def __init__(self, iterations):",
222 " self.iterations = iterations",
223 " self.prog_bar = '[]'",
224 " self.fill_char = '*'",
225 " self.width = 40",
226 " self.__update_amount(0)",
227 " if have_ipython:",
228 " self.animate = self.animate_ipython",
229 " else:",
230 " self.animate = self.animate_noipython",
231 "",
232 " def animate_ipython(self, iter):",
233 " clear_output()",
234 " print '\\r', self,",
235 " sys.stdout.flush()",
236 " self.update_iteration(iter + 1)",
237 "",
238 " def update_iteration(self, elapsed_iter):",
239 " self.__update_amount((elapsed_iter / float(self.iterations)) * 100.0)",
240 " self.prog_bar += ' %d of %s complete' % (elapsed_iter, self.iterations)",
241 "",
242 " def __update_amount(self, new_amount):",
243 " percent_done = int(round((new_amount / 100.0) * 100.0))",
244 " all_full = self.width - 2",
245 " num_hashes = int(round((percent_done / 100.0) * all_full))",
246 " self.prog_bar = '[' + self.fill_char * num_hashes + ' ' * (all_full - num_hashes) + ']'",
247 " pct_place = (len(self.prog_bar) // 2) - len(str(percent_done))",
248 " pct_string = '%d%%' % percent_done",
249 " self.prog_bar = self.prog_bar[0:pct_place] + \\",
250 " (pct_string + self.prog_bar[pct_place + len(pct_string):])",
251 "",
252 " def __str__(self):",
206 "import sys, time\n",
207 "try:\n",
208 " from IPython.core.display import clear_output\n",
209 " have_ipython = True\n",
210 "except ImportError:\n",
211 " have_ipython = False\n",
212 "\n",
213 "class ProgressBar:\n",
214 " def __init__(self, iterations):\n",
215 " self.iterations = iterations\n",
216 " self.prog_bar = '[]'\n",
217 " self.fill_char = '*'\n",
218 " self.width = 40\n",
219 " self.__update_amount(0)\n",
220 " if have_ipython:\n",
221 " self.animate = self.animate_ipython\n",
222 " else:\n",
223 " self.animate = self.animate_noipython\n",
224 "\n",
225 " def animate_ipython(self, iter):\n",
226 " print '\\r', self,\n",
227 " sys.stdout.flush()\n",
228 " self.update_iteration(iter + 1)\n",
229 "\n",
230 " def update_iteration(self, elapsed_iter):\n",
231 " self.__update_amount((elapsed_iter / float(self.iterations)) * 100.0)\n",
232 " self.prog_bar += ' %d of %s complete' % (elapsed_iter, self.iterations)\n",
233 "\n",
234 " def __update_amount(self, new_amount):\n",
235 " percent_done = int(round((new_amount / 100.0) * 100.0))\n",
236 " all_full = self.width - 2\n",
237 " num_hashes = int(round((percent_done / 100.0) * all_full))\n",
238 " self.prog_bar = '[' + self.fill_char * num_hashes + ' ' * (all_full - num_hashes) + ']'\n",
239 " pct_place = (len(self.prog_bar) // 2) - len(str(percent_done))\n",
240 " pct_string = '%d%%' % percent_done\n",
241 " self.prog_bar = self.prog_bar[0:pct_place] + \\\n",
242 " (pct_string + self.prog_bar[pct_place + len(pct_string):])\n",
243 "\n",
244 " def __str__(self):\n",
253 245 " return str(self.prog_bar)"
254 246 ],
255 247 "language": "python",
256 "outputs": [],
257 "prompt_number": 10
248 "metadata": {},
249 "outputs": []
258 250 },
259 251 {
260 252 "cell_type": "code",
261 253 "collapsed": false,
262 254 "input": [
263 "p = ProgressBar(1000)",
264 "for i in range(1001):",
255 "p = ProgressBar(1000)\n",
256 "for i in range(1001):\n",
265 257 " p.animate(i)"
266 258 ],
267 259 "language": "python",
268 "outputs": [],
269 "prompt_number": 11
260 "metadata": {},
261 "outputs": []
262 },
263 {
264 "cell_type": "code",
265 "collapsed": false,
266 "input": [],
267 "language": "python",
268 "metadata": {},
269 "outputs": []
270 270 }
271 ]
271 ],
272 "metadata": {}
272 273 }
273 274 ]
274 275 } No newline at end of file
@@ -3,180 +3,207 b''
3 3 "name": "Capturing Output"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "heading",
11 12 "level": 1,
13 "metadata": {},
12 14 "source": [
13 15 "Capturing Output with <tt>%%capture</tt>"
14 16 ]
15 17 },
16 18 {
17 19 "cell_type": "markdown",
20 "metadata": {},
18 21 "source": [
19 "One of IPython's new cell magics is `%%capture`, which captures stdout/err for a cell,",
22 "One of IPython's new cell magics is `%%capture`, which captures stdout/err for a cell,\n",
20 23 "and discards them or stores them in variables in your namespace."
21 24 ]
22 25 },
23 26 {
24 27 "cell_type": "code",
28 "collapsed": false,
25 29 "input": [
26 30 "import sys"
27 31 ],
28 32 "language": "python",
33 "metadata": {},
29 34 "outputs": []
30 35 },
31 36 {
32 37 "cell_type": "markdown",
38 "metadata": {},
33 39 "source": [
34 40 "By default, it just swallows it up. This is a simple way to suppress unwanted output."
35 41 ]
36 42 },
37 43 {
38 44 "cell_type": "code",
45 "collapsed": false,
39 46 "input": [
40 "%%capture",
41 "print 'hi, stdout'",
47 "%%capture\n",
48 "print 'hi, stdout'\n",
42 49 "print >> sys.stderr, 'hi, stderr'"
43 50 ],
44 51 "language": "python",
52 "metadata": {},
45 53 "outputs": []
46 54 },
47 55 {
48 56 "cell_type": "markdown",
57 "metadata": {},
49 58 "source": [
50 59 "If you specify a name, then stdout and stderr will be stored in an object in your namespace."
51 60 ]
52 61 },
53 62 {
54 63 "cell_type": "code",
64 "collapsed": false,
55 65 "input": [
56 "%%capture captured",
57 "print 'hi, stdout'",
66 "%%capture captured\n",
67 "print 'hi, stdout'\n",
58 68 "print >> sys.stderr, 'hi, stderr'"
59 69 ],
60 70 "language": "python",
71 "metadata": {},
61 72 "outputs": []
62 73 },
63 74 {
64 75 "cell_type": "code",
76 "collapsed": false,
65 77 "input": [
66 78 "captured"
67 79 ],
68 80 "language": "python",
81 "metadata": {},
69 82 "outputs": []
70 83 },
71 84 {
72 85 "cell_type": "markdown",
86 "metadata": {},
73 87 "source": [
74 88 "Calling the object writes the output to stdout/err as appropriate."
75 89 ]
76 90 },
77 91 {
78 92 "cell_type": "code",
93 "collapsed": false,
79 94 "input": [
80 95 "captured()"
81 96 ],
82 97 "language": "python",
98 "metadata": {},
83 99 "outputs": []
84 100 },
85 101 {
86 102 "cell_type": "code",
103 "collapsed": false,
87 104 "input": [
88 105 "captured.stdout"
89 106 ],
90 107 "language": "python",
108 "metadata": {},
91 109 "outputs": []
92 110 },
93 111 {
94 112 "cell_type": "code",
113 "collapsed": false,
95 114 "input": [
96 115 "captured.stderr"
97 116 ],
98 117 "language": "python",
118 "metadata": {},
99 119 "outputs": []
100 120 },
101 121 {
102 122 "cell_type": "markdown",
123 "metadata": {},
103 124 "source": [
104 125 "`%%capture` only captures stdout/err, not displaypub, so you can still do plots and use the display protocol inside %%capture"
105 126 ]
106 127 },
107 128 {
108 129 "cell_type": "code",
130 "collapsed": false,
109 131 "input": [
110 132 "%pylab inline"
111 133 ],
112 134 "language": "python",
135 "metadata": {},
113 136 "outputs": []
114 137 },
115 138 {
116 139 "cell_type": "code",
140 "collapsed": false,
117 141 "input": [
118 "%%capture wontshutup",
119 "",
120 "print \"setting up X\"",
121 "x = np.linspace(0,5,1000)",
122 "print \"step 2: constructing y-data\"",
123 "y = np.sin(x)",
124 "print \"step 3: display info about y\"",
125 "plt.plot(x,y)",
142 "%%capture wontshutup\n",
143 "\n",
144 "print \"setting up X\"\n",
145 "x = np.linspace(0,5,1000)\n",
146 "print \"step 2: constructing y-data\"\n",
147 "y = np.sin(x)\n",
148 "print \"step 3: display info about y\"\n",
149 "plt.plot(x,y)\n",
126 150 "print \"okay, I'm done now\""
127 151 ],
128 152 "language": "python",
153 "metadata": {},
129 154 "outputs": []
130 155 },
131 156 {
132 157 "cell_type": "code",
158 "collapsed": false,
133 159 "input": [
134 160 "wontshutup()"
135 161 ],
136 162 "language": "python",
163 "metadata": {},
137 164 "outputs": []
138 165 },
139 166 {
140 167 "cell_type": "markdown",
168 "metadata": {},
141 169 "source": [
142 170 "And you can selectively disable capturing stdout or stderr by passing `--no-stdout/err`."
143 171 ]
144 172 },
145 173 {
146 174 "cell_type": "code",
175 "collapsed": false,
147 176 "input": [
148 "%%capture cap --no-stderr",
149 "print 'hi, stdout'",
177 "%%capture cap --no-stderr\n",
178 "print 'hi, stdout'\n",
150 179 "print >> sys.stderr, \"hello, stderr\""
151 180 ],
152 181 "language": "python",
182 "metadata": {},
153 183 "outputs": []
154 184 },
155 185 {
156 186 "cell_type": "code",
187 "collapsed": false,
157 188 "input": [
158 189 "cap.stdout"
159 190 ],
160 191 "language": "python",
192 "metadata": {},
161 193 "outputs": []
162 194 },
163 195 {
164 196 "cell_type": "code",
197 "collapsed": false,
165 198 "input": [
166 199 "cap.stderr"
167 200 ],
168 201 "language": "python",
169 "outputs": []
170 },
171 {
172 "cell_type": "code",
173 "input": [
174 ""
175 ],
176 "language": "python",
202 "metadata": {},
177 203 "outputs": []
178 204 }
179 ]
205 ],
206 "metadata": {}
180 207 }
181 208 ]
182 209 } No newline at end of file
@@ -3,57 +3,64 b''
3 3 "name": "Script Magics"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "heading",
11 12 "level": 1,
13 "metadata": {},
12 14 "source": [
13 15 "Running Scripts from IPython"
14 16 ]
15 17 },
16 18 {
17 19 "cell_type": "markdown",
20 "metadata": {},
18 21 "source": [
19 "IPython has a `%%script` cell magic, which lets you run a cell in",
20 "a subprocess of any interpreter on your system, such as: bash, ruby, perl, zsh, R, etc.",
21 "",
22 "IPython has a `%%script` cell magic, which lets you run a cell in\n",
23 "a subprocess of any interpreter on your system, such as: bash, ruby, perl, zsh, R, etc.\n",
24 "\n",
22 25 "It can even be a script of your own, which expects input on stdin."
23 26 ]
24 27 },
25 28 {
26 29 "cell_type": "code",
30 "collapsed": false,
27 31 "input": [
28 32 "import sys"
29 33 ],
30 34 "language": "python",
35 "metadata": {},
31 36 "outputs": [],
32 37 "prompt_number": 1
33 38 },
34 39 {
35 40 "cell_type": "markdown",
41 "metadata": {},
36 42 "source": [
37 "To use it, simply pass a path or shell command to the program you want to run on the `%%script` line,",
43 "To use it, simply pass a path or shell command to the program you want to run on the `%%script` line,\n",
38 44 "and the rest of the cell will be run by that script, and stdout/err from the subprocess are captured and displayed."
39 45 ]
40 46 },
41 47 {
42 48 "cell_type": "code",
49 "collapsed": false,
43 50 "input": [
44 "%%script python",
45 "import sys",
51 "%%script python\n",
52 "import sys\n",
46 53 "print 'hello from Python %s' % sys.version"
47 54 ],
48 55 "language": "python",
56 "metadata": {},
49 57 "outputs": [
50 58 {
51 59 "output_type": "stream",
52 60 "stream": "stdout",
53 61 "text": [
54 "hello from Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) ",
55 "[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]",
56 ""
62 "hello from Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) \n",
63 "[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]\n"
57 64 ]
58 65 }
59 66 ],
@@ -61,20 +68,21 b''
61 68 },
62 69 {
63 70 "cell_type": "code",
71 "collapsed": false,
64 72 "input": [
65 "%%script python3",
66 "import sys",
73 "%%script python3\n",
74 "import sys\n",
67 75 "print('hello from Python: %s' % sys.version)"
68 76 ],
69 77 "language": "python",
78 "metadata": {},
70 79 "outputs": [
71 80 {
72 81 "output_type": "stream",
73 82 "stream": "stdout",
74 83 "text": [
75 "hello from Python: 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) ",
76 "[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]",
77 ""
84 "hello from Python: 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) \n",
85 "[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]\n"
78 86 ]
79 87 }
80 88 ],
@@ -82,26 +90,28 b''
82 90 },
83 91 {
84 92 "cell_type": "markdown",
93 "metadata": {},
85 94 "source": [
86 "IPython also creates aliases for a few common interpreters, such as bash, ruby, perl, etc.",
87 "",
95 "IPython also creates aliases for a few common interpreters, such as bash, ruby, perl, etc.\n",
96 "\n",
88 97 "These are all equivalent to `%%script <name>`"
89 98 ]
90 99 },
91 100 {
92 101 "cell_type": "code",
102 "collapsed": false,
93 103 "input": [
94 "%%ruby",
104 "%%ruby\n",
95 105 "puts \"Hello from Ruby #{RUBY_VERSION}\""
96 106 ],
97 107 "language": "python",
108 "metadata": {},
98 109 "outputs": [
99 110 {
100 111 "output_type": "stream",
101 112 "stream": "stdout",
102 113 "text": [
103 "Hello from Ruby 1.8.7",
104 ""
114 "Hello from Ruby 1.8.7\n"
105 115 ]
106 116 }
107 117 ],
@@ -109,18 +119,19 b''
109 119 },
110 120 {
111 121 "cell_type": "code",
122 "collapsed": false,
112 123 "input": [
113 "%%bash",
124 "%%bash\n",
114 125 "echo \"hello from $BASH\""
115 126 ],
116 127 "language": "python",
128 "metadata": {},
117 129 "outputs": [
118 130 {
119 131 "output_type": "stream",
120 132 "stream": "stdout",
121 133 "text": [
122 "hello from /usr/local/bin/bash",
123 ""
134 "hello from /usr/local/bin/bash\n"
124 135 ]
125 136 }
126 137 ],
@@ -129,40 +140,41 b''
129 140 {
130 141 "cell_type": "heading",
131 142 "level": 2,
143 "metadata": {},
132 144 "source": [
133 145 "Capturing output"
134 146 ]
135 147 },
136 148 {
137 149 "cell_type": "markdown",
150 "metadata": {},
138 151 "source": [
139 152 "You can also capture stdout/err from these subprocesses into Python variables, instead of letting them go directly to stdout/err"
140 153 ]
141 154 },
142 155 {
143 156 "cell_type": "code",
157 "collapsed": false,
144 158 "input": [
145 "%%bash",
146 "echo \"hi, stdout\"",
147 "echo \"hello, stderr\" >&2",
148 ""
159 "%%bash\n",
160 "echo \"hi, stdout\"\n",
161 "echo \"hello, stderr\" >&2\n"
149 162 ],
150 163 "language": "python",
164 "metadata": {},
151 165 "outputs": [
152 166 {
153 167 "output_type": "stream",
154 168 "stream": "stdout",
155 169 "text": [
156 "hi, stdout",
157 ""
170 "hi, stdout\n"
158 171 ]
159 172 },
160 173 {
161 174 "output_type": "stream",
162 175 "stream": "stderr",
163 176 "text": [
164 "hello, stderr",
165 ""
177 "hello, stderr\n"
166 178 ]
167 179 }
168 180 ],
@@ -170,32 +182,35 b''
170 182 },
171 183 {
172 184 "cell_type": "code",
185 "collapsed": false,
173 186 "input": [
174 "%%bash --out output --err error",
175 "echo \"hi, stdout\"",
187 "%%bash --out output --err error\n",
188 "echo \"hi, stdout\"\n",
176 189 "echo \"hello, stderr\" >&2"
177 190 ],
178 191 "language": "python",
192 "metadata": {},
179 193 "outputs": [],
180 194 "prompt_number": 7
181 195 },
182 196 {
183 197 "cell_type": "code",
198 "collapsed": false,
184 199 "input": [
185 "print error",
200 "print error\n",
186 201 "print output"
187 202 ],
188 203 "language": "python",
204 "metadata": {},
189 205 "outputs": [
190 206 {
191 207 "output_type": "stream",
192 208 "stream": "stdout",
193 209 "text": [
194 "hello, stderr",
195 "",
196 "hi, stdout",
197 "",
198 ""
210 "hello, stderr\n",
211 "\n",
212 "hi, stdout\n",
213 "\n"
199 214 ]
200 215 }
201 216 ],
@@ -204,37 +219,40 b''
204 219 {
205 220 "cell_type": "heading",
206 221 "level": 2,
222 "metadata": {},
207 223 "source": [
208 224 "Background Scripts"
209 225 ]
210 226 },
211 227 {
212 228 "cell_type": "markdown",
229 "metadata": {},
213 230 "source": [
214 "These scripts can be run in the background, by adding the `--bg` flag.",
215 "",
216 "When you do this, output is discarded unless you use the `--out/err`",
231 "These scripts can be run in the background, by adding the `--bg` flag.\n",
232 "\n",
233 "When you do this, output is discarded unless you use the `--out/err`\n",
217 234 "flags to store output as above."
218 235 ]
219 236 },
220 237 {
221 238 "cell_type": "code",
239 "collapsed": false,
222 240 "input": [
223 "%%ruby --bg --out ruby_lines",
224 "for n in 1...10",
225 " sleep 1",
226 " puts \"line #{n}\"",
227 " STDOUT.flush",
241 "%%ruby --bg --out ruby_lines\n",
242 "for n in 1...10\n",
243 " sleep 1\n",
244 " puts \"line #{n}\"\n",
245 " STDOUT.flush\n",
228 246 "end"
229 247 ],
230 248 "language": "python",
249 "metadata": {},
231 250 "outputs": [
232 251 {
233 252 "output_type": "stream",
234 253 "stream": "stdout",
235 254 "text": [
236 "Starting job # 0 in a separate thread.",
237 ""
255 "Starting job # 0 in a separate thread.\n"
238 256 ]
239 257 }
240 258 ],
@@ -242,23 +260,26 b''
242 260 },
243 261 {
244 262 "cell_type": "markdown",
263 "metadata": {},
245 264 "source": [
246 "When you do store output of a background thread, these are the stdout/err *pipes*,",
265 "When you do store output of a background thread, these are the stdout/err *pipes*,\n",
247 266 "rather than the text of the output."
248 267 ]
249 268 },
250 269 {
251 270 "cell_type": "code",
271 "collapsed": false,
252 272 "input": [
253 273 "ruby_lines"
254 274 ],
255 275 "language": "python",
276 "metadata": {},
256 277 "outputs": [
257 278 {
258 279 "output_type": "pyout",
259 280 "prompt_number": 10,
260 281 "text": [
261 "<open file '<fdopen>', mode 'rb' at 0x10dc651e0>"
282 "<open file '<fdopen>', mode 'rb' at 0x10a4be660>"
262 283 ]
263 284 }
264 285 ],
@@ -266,26 +287,27 b''
266 287 },
267 288 {
268 289 "cell_type": "code",
290 "collapsed": false,
269 291 "input": [
270 292 "print ruby_lines.read()"
271 293 ],
272 294 "language": "python",
295 "metadata": {},
273 296 "outputs": [
274 297 {
275 298 "output_type": "stream",
276 299 "stream": "stdout",
277 300 "text": [
278 "line 1",
279 "line 2",
280 "line 3",
281 "line 4",
282 "line 5",
283 "line 6",
284 "line 7",
285 "line 8",
286 "line 9",
287 "",
288 ""
301 "line 1\n",
302 "line 2\n",
303 "line 3\n",
304 "line 4\n",
305 "line 5\n",
306 "line 6\n",
307 "line 7\n",
308 "line 8\n",
309 "line 9\n",
310 "\n"
289 311 ]
290 312 }
291 313 ],
@@ -294,31 +316,34 b''
294 316 {
295 317 "cell_type": "heading",
296 318 "level": 2,
319 "metadata": {},
297 320 "source": [
298 321 "Arguments to subcommand"
299 322 ]
300 323 },
301 324 {
302 325 "cell_type": "markdown",
326 "metadata": {},
303 327 "source": [
304 "You can pass arguments the subcommand as well,",
328 "You can pass arguments the subcommand as well,\n",
305 329 "such as this example instructing Python to use integer division from Python 3:"
306 330 ]
307 331 },
308 332 {
309 333 "cell_type": "code",
334 "collapsed": false,
310 335 "input": [
311 "%%script python -Qnew",
336 "%%script python -Qnew\n",
312 337 "print 1/3"
313 338 ],
314 339 "language": "python",
340 "metadata": {},
315 341 "outputs": [
316 342 {
317 343 "output_type": "stream",
318 344 "stream": "stdout",
319 345 "text": [
320 "0.333333333333",
321 ""
346 "0.333333333333\n"
322 347 ]
323 348 }
324 349 ],
@@ -326,30 +351,31 b''
326 351 },
327 352 {
328 353 "cell_type": "markdown",
354 "metadata": {},
329 355 "source": [
330 "You can really specify *any* program for `%%script`,",
356 "You can really specify *any* program for `%%script`,\n",
331 357 "for instance here is a 'program' that echos the lines of stdin, with delays between each line."
332 358 ]
333 359 },
334 360 {
335 361 "cell_type": "code",
362 "collapsed": false,
336 363 "input": [
337 "%%script --bg --out bashout bash -c \"while read line; do echo $line; sleep 1; done\"",
338 "line 1",
339 "line 2",
340 "line 3",
341 "line 4",
342 "line 5",
343 ""
364 "%%script --bg --out bashout bash -c \"while read line; do echo $line; sleep 1; done\"\n",
365 "line 1\n",
366 "line 2\n",
367 "line 3\n",
368 "line 4\n",
369 "line 5\n"
344 370 ],
345 371 "language": "python",
372 "metadata": {},
346 373 "outputs": [
347 374 {
348 375 "output_type": "stream",
349 376 "stream": "stdout",
350 377 "text": [
351 "Starting job # 2 in a separate thread.",
352 ""
378 "Starting job # 2 in a separate thread.\n"
353 379 ]
354 380 }
355 381 ],
@@ -357,65 +383,62 b''
357 383 },
358 384 {
359 385 "cell_type": "markdown",
386 "metadata": {},
360 387 "source": [
361 "Remember, since the output of a background script is just the stdout pipe,",
388 "Remember, since the output of a background script is just the stdout pipe,\n",
362 389 "you can read it as lines become available:"
363 390 ]
364 391 },
365 392 {
366 393 "cell_type": "code",
394 "collapsed": false,
367 395 "input": [
368 "import time",
369 "tic = time.time()",
370 "line = True",
371 "while True:",
372 " line = bashout.readline()",
373 " if not line:",
374 " break",
375 " sys.stdout.write(\"%.1fs: %s\" %(time.time()-tic, line))",
376 " sys.stdout.flush()",
377 ""
396 "import time\n",
397 "tic = time.time()\n",
398 "line = True\n",
399 "while True:\n",
400 " line = bashout.readline()\n",
401 " if not line:\n",
402 " break\n",
403 " sys.stdout.write(\"%.1fs: %s\" %(time.time()-tic, line))\n",
404 " sys.stdout.flush()\n"
378 405 ],
379 406 "language": "python",
407 "metadata": {},
380 408 "outputs": [
381 409 {
382 410 "output_type": "stream",
383 411 "stream": "stdout",
384 412 "text": [
385 "0.0s: line 1",
386 ""
413 "0.0s: line 1\n"
387 414 ]
388 415 },
389 416 {
390 417 "output_type": "stream",
391 418 "stream": "stdout",
392 419 "text": [
393 "1.0s: line 2",
394 ""
420 "1.0s: line 2\n"
395 421 ]
396 422 },
397 423 {
398 424 "output_type": "stream",
399 425 "stream": "stdout",
400 426 "text": [
401 "2.0s: line 3",
402 ""
427 "2.0s: line 3\n"
403 428 ]
404 429 },
405 430 {
406 431 "output_type": "stream",
407 432 "stream": "stdout",
408 433 "text": [
409 "3.0s: line 4",
410 ""
434 "3.0s: line 4\n"
411 435 ]
412 436 },
413 437 {
414 438 "output_type": "stream",
415 439 "stream": "stdout",
416 440 "text": [
417 "4.0s: line 5",
418 ""
441 "4.0s: line 5\n"
419 442 ]
420 443 }
421 444 ],
@@ -424,25 +447,28 b''
424 447 {
425 448 "cell_type": "heading",
426 449 "level": 2,
450 "metadata": {},
427 451 "source": [
428 452 "Configuring the default ScriptMagics"
429 453 ]
430 454 },
431 455 {
432 456 "cell_type": "markdown",
457 "metadata": {},
433 458 "source": [
434 "The list of aliased script magics is configurable.",
435 "",
436 "The default is to pick from a few common interpreters, and use them if found, but you can specify your own in ipython_config.py:",
437 "",
438 " c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']",
439 "",
440 "And if any of these programs do not apear on your default PATH, then you would also need to specify their location with:",
441 "",
459 "The list of aliased script magics is configurable.\n",
460 "\n",
461 "The default is to pick from a few common interpreters, and use them if found, but you can specify your own in ipython_config.py:\n",
462 "\n",
463 " c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']\n",
464 "\n",
465 "And if any of these programs do not apear on your default PATH, then you would also need to specify their location with:\n",
466 "\n",
442 467 " c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}"
443 468 ]
444 469 }
445 ]
470 ],
471 "metadata": {}
446 472 }
447 473 ]
448 474 } No newline at end of file
@@ -3,12 +3,14 b''
3 3 "name": "cython_extension"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "heading",
11 12 "level": 1,
13 "metadata": {},
12 14 "source": [
13 15 "Cython Magic Functions Extension"
14 16 ]
@@ -16,116 +18,134 b''
16 18 {
17 19 "cell_type": "heading",
18 20 "level": 2,
21 "metadata": {},
19 22 "source": [
20 23 "Loading the extension"
21 24 ]
22 25 },
23 26 {
24 27 "cell_type": "markdown",
28 "metadata": {},
25 29 "source": [
26 30 "IPtyhon has a `cythonmagic` extension that contains a number of magic functions for working with Cython code. This extension can be loaded using the `%load_ext` magic as follows:"
27 31 ]
28 32 },
29 33 {
30 34 "cell_type": "code",
35 "collapsed": false,
31 36 "input": [
32 37 "%load_ext cythonmagic"
33 38 ],
34 39 "language": "python",
40 "metadata": {},
35 41 "outputs": [],
36 42 "prompt_number": 1
37 43 },
38 44 {
39 45 "cell_type": "heading",
40 46 "level": 2,
47 "metadata": {},
41 48 "source": [
42 49 "The %cython_inline magic"
43 50 ]
44 51 },
45 52 {
46 53 "cell_type": "markdown",
54 "metadata": {},
47 55 "source": [
48 56 "The `%%cython_inline` magic uses `Cython.inline` to compile a Cython expression. This allows you to enter and run a function body with Cython code. Use a bare `return` statement to return values. "
49 57 ]
50 58 },
51 59 {
52 60 "cell_type": "code",
61 "collapsed": false,
53 62 "input": [
54 63 "a = 10\n",
55 64 "b = 20"
56 65 ],
57 66 "language": "python",
67 "metadata": {},
58 68 "outputs": [],
59 "prompt_number": 8
69 "prompt_number": 2
60 70 },
61 71 {
62 72 "cell_type": "code",
73 "collapsed": false,
63 74 "input": [
64 75 "%%cython_inline\n",
65 76 "return a+b"
66 77 ],
67 78 "language": "python",
79 "metadata": {},
68 80 "outputs": [
69 81 {
70 82 "output_type": "pyout",
71 "prompt_number": 9,
83 "prompt_number": 3,
72 84 "text": [
73 85 "30"
74 86 ]
75 87 }
76 88 ],
77 "prompt_number": 9
89 "prompt_number": 3
78 90 },
79 91 {
80 92 "cell_type": "heading",
81 93 "level": 2,
94 "metadata": {},
82 95 "source": [
83 96 "The %cython_pyximport magic"
84 97 ]
85 98 },
86 99 {
87 100 "cell_type": "markdown",
101 "metadata": {},
88 102 "source": [
89 103 "The `%%cython_pyximport` magic allows you to enter arbitrary Cython code into a cell. That Cython code is written as a `.pyx` file in the current working directory and then imported using `pyximport`. You have the specify the name of the module that the Code will appear in. All symbols from the module are imported automatically by the magic function."
90 104 ]
91 105 },
92 106 {
93 107 "cell_type": "code",
108 "collapsed": false,
94 109 "input": [
95 110 "%%cython_pyximport foo\n",
96 111 "def f(x):\n",
97 112 " return 4.0*x"
98 113 ],
99 114 "language": "python",
115 "metadata": {},
100 116 "outputs": [],
101 "prompt_number": 18
117 "prompt_number": 4
102 118 },
103 119 {
104 120 "cell_type": "code",
121 "collapsed": false,
105 122 "input": [
106 123 "f(10)"
107 124 ],
108 125 "language": "python",
126 "metadata": {},
109 127 "outputs": [
110 128 {
111 129 "output_type": "pyout",
112 "prompt_number": 19,
130 "prompt_number": 5,
113 131 "text": [
114 132 "40.0"
115 133 ]
116 134 }
117 135 ],
118 "prompt_number": 19
136 "prompt_number": 5
119 137 },
120 138 {
121 139 "cell_type": "heading",
122 140 "level": 2,
141 "metadata": {},
123 142 "source": [
124 143 "The %cython magic"
125 144 ]
126 145 },
127 146 {
128 147 "cell_type": "markdown",
148 "metadata": {},
129 149 "source": [
130 150 "Probably the most important magic is the `%cython` magic. This is similar to the `%%cython_pyximport` magic, but doesn't require you to specify a module name. Instead, the `%%cython` magic uses manages everything using temporary files in the `~/.cython/magic` directory. All of the symbols in the Cython module are imported automatically by the magic.\n",
131 151 "\n",
@@ -134,6 +154,7 b''
134 154 },
135 155 {
136 156 "cell_type": "code",
157 "collapsed": false,
137 158 "input": [
138 159 "%%cython\n",
139 160 "cimport cython\n",
@@ -165,15 +186,18 b''
165 186 " return optprice"
166 187 ],
167 188 "language": "python",
189 "metadata": {},
168 190 "outputs": [],
169 191 "prompt_number": 6
170 192 },
171 193 {
172 194 "cell_type": "code",
195 "collapsed": false,
173 196 "input": [
174 197 "black_scholes(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
175 198 ],
176 199 "language": "python",
200 "metadata": {},
177 201 "outputs": [
178 202 {
179 203 "output_type": "pyout",
@@ -187,35 +211,40 b''
187 211 },
188 212 {
189 213 "cell_type": "code",
214 "collapsed": false,
190 215 "input": [
191 216 "%timeit black_scholes(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)"
192 217 ],
193 218 "language": "python",
219 "metadata": {},
194 220 "outputs": [
195 221 {
196 222 "output_type": "stream",
197 223 "stream": "stdout",
198 224 "text": [
199 "1000000 loops, best of 3: 621 ns per loop\n"
225 "1000000 loops, best of 3: 821 ns per loop\n"
200 226 ]
201 227 }
202 228 ],
203 "prompt_number": 14
229 "prompt_number": 8
204 230 },
205 231 {
206 232 "cell_type": "markdown",
233 "metadata": {},
207 234 "source": [
208 235 "Cython allows you to specify additional libraries to be linked with your extension, you can do so with the `-l` flag (also spelled `--lib`). Note that this flag can be passed more than once to specify multiple libraries, such as `-lm -llib2 --lib lib3`. Here's a simple example of how to access the system math library:"
209 236 ]
210 237 },
211 238 {
212 239 "cell_type": "code",
240 "collapsed": false,
213 241 "input": [
214 242 "%%cython -lm\n",
215 243 "from libc.math cimport sin\n",
216 244 "print 'sin(1)=', sin(1)"
217 245 ],
218 246 "language": "python",
247 "metadata": {},
219 248 "outputs": [
220 249 {
221 250 "output_type": "stream",
@@ -225,15 +254,17 b''
225 254 ]
226 255 }
227 256 ],
228 "prompt_number": 2
257 "prompt_number": 9
229 258 },
230 259 {
231 260 "cell_type": "markdown",
261 "metadata": {},
232 262 "source": [
233 263 "You can similarly use the `-I/--include` flag to add include directories to the search path, and `-c/--compile-args` to add extra flags that are passed to Cython via the `extra_compile_args` of the distutils `Extension` class. Please see [the Cython docs on C library usage](http://docs.cython.org/src/tutorial/clibraries.html) for more details on the use of these flags."
234 264 ]
235 265 }
236 ]
266 ],
267 "metadata": {}
237 268 }
238 269 ]
239 270 } No newline at end of file
@@ -3,42 +3,73 b''
3 3 "name": "display_protocol"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
11 "cell_type": "heading",
12 "level": 1,
13 "metadata": {},
14 "source": [
15 "Using the IPython display protocol for your own objects"
16 ]
17 },
18 {
19 "cell_type": "markdown",
20 "metadata": {},
21 "source": [
22 "IPython extends the idea of the ``__repr__`` method in Python to support multiple representations for a given\n",
23 "object, which clients can use to display the object according to their capabilities. An object can return multiple\n",
24 "representations of itself by implementing special methods, and you can also define at runtime custom display \n",
25 "functions for existing objects whose methods you can't or won't modify. In this notebook, we show how both approaches work.\n",
26 "\n",
27 "<br/>\n",
28 "**Note:** this notebook has had all output cells stripped out so we can include it in the IPython documentation with \n",
29 "a minimal file size. You'll need to manually execute the cells to see the output (you can run all of them with the \n",
30 "\"Run All\" button, or execute each individually)."
31 ]
32 },
33 {
34 "cell_type": "markdown",
35 "metadata": {},
36 "source": [
37 "Parts of this notebook need the inline matplotlib backend:"
38 ]
39 },
40 {
41 "cell_type": "code",
42 "collapsed": false,
43 "input": [
44 "%pylab inline"
45 ],
46 "language": "python",
47 "metadata": {},
48 "outputs": []
49 },
50 {
51 "cell_type": "heading",
52 "level": 2,
53 "metadata": {},
54 "source": [
55 "Custom-built classes with dedicated ``_repr_*_`` methods"
56 ]
57 },
58 {
10 59 "cell_type": "markdown",
60 "metadata": {},
11 61 "source": [
12 "# Using the IPython display protocol for your own objects",
13 "",
14 "IPython extends the idea of the ``__repr__`` method in Python to support multiple representations for a given",
15 "object, which clients can use to display the object according to their capabilities. An object can return multiple",
16 "representations of itself by implementing special methods, and you can also define at runtime custom display ",
17 "functions for existing objects whose methods you can't or won't modify. In this notebook, we show how both approaches work.",
18 "",
19 "<br/>",
20 "**Note:** this notebook has had all output cells stripped out so we can include it in the IPython documentation with ",
21 "a minimal file size. You'll need to manually execute the cells to see the output (you can run all of them with the ",
22 "\"Run All\" button, or execute each individually). You must start this notebook with",
23 "<pre>",
24 "ipython notebook --pylab inline",
25 "</pre>",
26 "",
27 "to ensure pylab support is available for plots.",
28 "",
29 "## Custom-built classes with dedicated ``_repr_*_`` methods",
30 "",
31 "In our first example, we illustrate how objects can expose directly to IPython special representations of",
32 "themselves, by providing methods such as ``_repr_svg_``, ``_repr_png_``, ``_repr_latex_``, etc. For a full",
33 "list of the special ``_repr_*_`` methods supported, see the code in ``IPython.core.displaypub``.",
34 "",
35 "As an illustration, we build a class that holds data generated by sampling a Gaussian distribution with given mean ",
36 "and variance. The class can display itself in a variety of ways: as a LaTeX expression or as an image in PNG or SVG ",
37 "format. Each frontend can then decide which representation it can handle.",
38 "Further, we illustrate how to expose directly to the user the ability to directly access the various alternate ",
39 "representations (since by default displaying the object itself will only show one, and which is shown will depend on the ",
40 "required representations that even cache necessary data in cases where it may be expensive to compute.",
41 "",
62 "In our first example, we illustrate how objects can expose directly to IPython special representations of\n",
63 "themselves, by providing methods such as ``_repr_svg_``, ``_repr_png_``, ``_repr_latex_``, etc. For a full\n",
64 "list of the special ``_repr_*_`` methods supported, see the code in ``IPython.core.displaypub``.\n",
65 "\n",
66 "As an illustration, we build a class that holds data generated by sampling a Gaussian distribution with given mean \n",
67 "and variance. The class can display itself in a variety of ways: as a LaTeX expression or as an image in PNG or SVG \n",
68 "format. Each frontend can then decide which representation it can handle.\n",
69 "Further, we illustrate how to expose directly to the user the ability to directly access the various alternate \n",
70 "representations (since by default displaying the object itself will only show one, and which is shown will depend on the \n",
71 "required representations that even cache necessary data in cases where it may be expensive to compute.\n",
72 "\n",
42 73 "The next cell defines the Gaussian class:"
43 74 ]
44 75 },
@@ -46,81 +77,82 b''
46 77 "cell_type": "code",
47 78 "collapsed": false,
48 79 "input": [
49 "from IPython.core.pylabtools import print_figure",
50 "from IPython.core.display import Image, SVG, Math",
51 "",
52 "class Gaussian(object):",
53 " \"\"\"A simple object holding data sampled from a Gaussian distribution.",
54 " \"\"\"",
55 " def __init__(self, mean=0, std=1, size=1000):",
56 " self.data = np.random.normal(mean, std, size)",
57 " self.mean = mean",
58 " self.std = std",
59 " self.size = size",
60 " # For caching plots that may be expensive to compute",
61 " self._png_data = None",
62 " self._svg_data = None",
63 " ",
64 " def _figure_data(self, format):",
65 " fig, ax = plt.subplots()",
66 " ax.plot(self.data, 'o')",
67 " ax.set_title(self._repr_latex_())",
68 " data = print_figure(fig, format)",
69 " # We MUST close the figure, otherwise IPython's display machinery",
70 " # will pick it up and send it as output, resulting in a double display",
71 " plt.close(fig)",
72 " return data",
73 " ",
74 " # Here we define the special repr methods that provide the IPython display protocol",
75 " # Note that for the two figures, we cache the figure data once computed.",
76 " ",
77 " def _repr_png_(self):",
78 " if self._png_data is None:",
79 " self._png_data = self._figure_data('png')",
80 " return self._png_data",
81 "",
82 "",
83 " def _repr_svg_(self):",
84 " if self._svg_data is None:",
85 " self._svg_data = self._figure_data('svg')",
86 " return self._svg_data",
87 " ",
88 " def _repr_latex_(self):",
89 " return r'$\\mathcal{N}(\\mu=%.2g, \\sigma=%.2g),\\ N=%d$' % (self.mean,",
90 " self.std, self.size)",
91 " ",
92 " # We expose as properties some of the above reprs, so that the user can see them",
93 " # directly (since otherwise the client dictates which one it shows by default)",
94 " @property",
95 " def png(self):",
96 " return Image(self._repr_png_(), embed=True)",
97 " ",
98 " @property",
99 " def svg(self):",
100 " return SVG(self._repr_svg_())",
101 " ",
102 " @property",
103 " def latex(self):",
104 " return Math(self._repr_svg_())",
105 " ",
106 " # An example of using a property to display rich information, in this case",
107 " # the histogram of the distribution. We've hardcoded the format to be png",
108 " # in this case, but in production code it would be trivial to make it an option",
109 " @property",
110 " def hist(self):",
111 " fig, ax = plt.subplots()",
112 " ax.hist(self.data, bins=100)",
113 " ax.set_title(self._repr_latex_())",
114 " data = print_figure(fig, 'png')",
115 " plt.close(fig)",
80 "from IPython.core.pylabtools import print_figure\n",
81 "from IPython.display import Image, SVG, Math\n",
82 "\n",
83 "class Gaussian(object):\n",
84 " \"\"\"A simple object holding data sampled from a Gaussian distribution.\n",
85 " \"\"\"\n",
86 " def __init__(self, mean=0, std=1, size=1000):\n",
87 " self.data = np.random.normal(mean, std, size)\n",
88 " self.mean = mean\n",
89 " self.std = std\n",
90 " self.size = size\n",
91 " # For caching plots that may be expensive to compute\n",
92 " self._png_data = None\n",
93 " self._svg_data = None\n",
94 " \n",
95 " def _figure_data(self, format):\n",
96 " fig, ax = plt.subplots()\n",
97 " ax.plot(self.data, 'o')\n",
98 " ax.set_title(self._repr_latex_())\n",
99 " data = print_figure(fig, format)\n",
100 " # We MUST close the figure, otherwise IPython's display machinery\n",
101 " # will pick it up and send it as output, resulting in a double display\n",
102 " plt.close(fig)\n",
103 " return data\n",
104 " \n",
105 " # Here we define the special repr methods that provide the IPython display protocol\n",
106 " # Note that for the two figures, we cache the figure data once computed.\n",
107 " \n",
108 " def _repr_png_(self):\n",
109 " if self._png_data is None:\n",
110 " self._png_data = self._figure_data('png')\n",
111 " return self._png_data\n",
112 "\n",
113 "\n",
114 " def _repr_svg_(self):\n",
115 " if self._svg_data is None:\n",
116 " self._svg_data = self._figure_data('svg')\n",
117 " return self._svg_data\n",
118 " \n",
119 " def _repr_latex_(self):\n",
120 " return r'$\\mathcal{N}(\\mu=%.2g, \\sigma=%.2g),\\ N=%d$' % (self.mean,\n",
121 " self.std, self.size)\n",
122 " \n",
123 " # We expose as properties some of the above reprs, so that the user can see them\n",
124 " # directly (since otherwise the client dictates which one it shows by default)\n",
125 " @property\n",
126 " def png(self):\n",
127 " return Image(self._repr_png_(), embed=True)\n",
128 " \n",
129 " @property\n",
130 " def svg(self):\n",
131 " return SVG(self._repr_svg_())\n",
132 " \n",
133 " @property\n",
134 " def latex(self):\n",
135 " return Math(self._repr_svg_())\n",
136 " \n",
137 " # An example of using a property to display rich information, in this case\n",
138 " # the histogram of the distribution. We've hardcoded the format to be png\n",
139 " # in this case, but in production code it would be trivial to make it an option\n",
140 " @property\n",
141 " def hist(self):\n",
142 " fig, ax = plt.subplots()\n",
143 " ax.hist(self.data, bins=100)\n",
144 " ax.set_title(self._repr_latex_())\n",
145 " data = print_figure(fig, 'png')\n",
146 " plt.close(fig)\n",
116 147 " return Image(data, embed=True)"
117 148 ],
118 149 "language": "python",
119 "outputs": [],
120 "prompt_number": 1
150 "metadata": {},
151 "outputs": []
121 152 },
122 153 {
123 154 "cell_type": "markdown",
155 "metadata": {},
124 156 "source": [
125 157 "Now, we create an instance of the Gaussian distribution, whose default representation will be its LaTeX form:"
126 158 ]
@@ -129,15 +161,16 b''
129 161 "cell_type": "code",
130 162 "collapsed": false,
131 163 "input": [
132 "x = Gaussian()",
164 "x = Gaussian()\n",
133 165 "x"
134 166 ],
135 167 "language": "python",
136 "outputs": [],
137 "prompt_number": 2
168 "metadata": {},
169 "outputs": []
138 170 },
139 171 {
140 172 "cell_type": "markdown",
173 "metadata": {},
141 174 "source": [
142 175 "We can view the data in png or svg formats:"
143 176 ]
@@ -149,8 +182,8 b''
149 182 "x.png"
150 183 ],
151 184 "language": "python",
152 "outputs": [],
153 "prompt_number": 3
185 "metadata": {},
186 "outputs": []
154 187 },
155 188 {
156 189 "cell_type": "code",
@@ -159,13 +192,14 b''
159 192 "x.svg"
160 193 ],
161 194 "language": "python",
162 "outputs": [],
163 "prompt_number": 4
195 "metadata": {},
196 "outputs": []
164 197 },
165 198 {
166 199 "cell_type": "markdown",
200 "metadata": {},
167 201 "source": [
168 "Since IPython only displays by default as an ``Out[]`` cell the result of the last computation, we can use the",
202 "Since IPython only displays by default as an ``Out[]`` cell the result of the last computation, we can use the\n",
169 203 "``display()`` function to show more than one representation in a single cell:"
170 204 ]
171 205 },
@@ -173,15 +207,16 b''
173 207 "cell_type": "code",
174 208 "collapsed": false,
175 209 "input": [
176 "display(x.png)",
210 "display(x.png)\n",
177 211 "display(x.svg)"
178 212 ],
179 213 "language": "python",
180 "outputs": [],
181 "prompt_number": 5
214 "metadata": {},
215 "outputs": []
182 216 },
183 217 {
184 218 "cell_type": "markdown",
219 "metadata": {},
185 220 "source": [
186 221 "Now let's create a new Gaussian with different parameters"
187 222 ]
@@ -190,15 +225,16 b''
190 225 "cell_type": "code",
191 226 "collapsed": false,
192 227 "input": [
193 "x2 = Gaussian(0.5, 0.2, 2000)",
228 "x2 = Gaussian(0.5, 0.2, 2000)\n",
194 229 "x2"
195 230 ],
196 231 "language": "python",
197 "outputs": [],
198 "prompt_number": 6
232 "metadata": {},
233 "outputs": []
199 234 },
200 235 {
201 236 "cell_type": "markdown",
237 "metadata": {},
202 238 "source": [
203 239 "We can easily compare them by displaying their histograms"
204 240 ]
@@ -207,26 +243,27 b''
207 243 "cell_type": "code",
208 244 "collapsed": false,
209 245 "input": [
210 "display(x.hist)",
246 "display(x.hist)\n",
211 247 "display(x2.hist)"
212 248 ],
213 249 "language": "python",
214 "outputs": [],
215 "prompt_number": 7
250 "metadata": {},
251 "outputs": []
216 252 },
217 253 {
218 254 "cell_type": "markdown",
255 "metadata": {},
219 256 "source": [
220 "## Adding IPython display support to existing objects",
221 "",
222 "When you are directly writing your own classes, you can adapt them for display in IPython by ",
223 "following the above example. But in practice, we often need to work with existing code we",
224 "can't modify. ",
225 "",
226 "We now illustrate how to add these kinds of extended display capabilities to existing objects.",
227 "We will use the numpy polynomials and change their default representation to be a formatted",
228 "LaTeX expression.",
229 "",
257 "## Adding IPython display support to existing objects\n",
258 "\n",
259 "When you are directly writing your own classes, you can adapt them for display in IPython by \n",
260 "following the above example. But in practice, we often need to work with existing code we\n",
261 "can't modify. \n",
262 "\n",
263 "We now illustrate how to add these kinds of extended display capabilities to existing objects.\n",
264 "We will use the numpy polynomials and change their default representation to be a formatted\n",
265 "LaTeX expression.\n",
266 "\n",
230 267 "First, consider how a numpy polynomial object renders by default:"
231 268 ]
232 269 },
@@ -234,48 +271,50 b''
234 271 "cell_type": "code",
235 272 "collapsed": false,
236 273 "input": [
237 "p = np.polynomial.Polynomial([1,2,3], [-10, 10])",
274 "p = np.polynomial.Polynomial([1,2,3], [-10, 10])\n",
238 275 "p"
239 276 ],
240 277 "language": "python",
241 "outputs": [],
242 "prompt_number": 8
278 "metadata": {},
279 "outputs": []
243 280 },
244 281 {
245 282 "cell_type": "markdown",
283 "metadata": {},
246 284 "source": [
247 285 "Next, we define a function that pretty-prints a polynomial as a LaTeX string:"
248 286 ]
249 287 },
250 288 {
251 289 "cell_type": "code",
252 "collapsed": true,
290 "collapsed": false,
253 291 "input": [
254 "def poly2latex(p):",
255 " terms = ['%.2g' % p.coef[0]]",
256 " if len(p) > 1:",
257 " term = 'x'",
258 " c = p.coef[1]",
259 " if c!=1:",
260 " term = ('%.2g ' % c) + term",
261 " terms.append(term)",
262 " if len(p) > 2:",
263 " for i in range(2, len(p)):",
264 " term = 'x^%d' % i",
265 " c = p.coef[i]",
266 " if c!=1:",
267 " term = ('%.2g ' % c) + term",
268 " terms.append(term)",
269 " px = '$P(x)=%s$' % '+'.join(terms)",
270 " dom = r', domain: $[%.2g,\\ %.2g]$' % tuple(p.domain)",
292 "def poly2latex(p):\n",
293 " terms = ['%.2g' % p.coef[0]]\n",
294 " if len(p) > 1:\n",
295 " term = 'x'\n",
296 " c = p.coef[1]\n",
297 " if c!=1:\n",
298 " term = ('%.2g ' % c) + term\n",
299 " terms.append(term)\n",
300 " if len(p) > 2:\n",
301 " for i in range(2, len(p)):\n",
302 " term = 'x^%d' % i\n",
303 " c = p.coef[i]\n",
304 " if c!=1:\n",
305 " term = ('%.2g ' % c) + term\n",
306 " terms.append(term)\n",
307 " px = '$P(x)=%s$' % '+'.join(terms)\n",
308 " dom = r', domain: $[%.2g,\\ %.2g]$' % tuple(p.domain)\n",
271 309 " return px+dom"
272 310 ],
273 311 "language": "python",
274 "outputs": [],
275 "prompt_number": 9
312 "metadata": {},
313 "outputs": []
276 314 },
277 315 {
278 316 "cell_type": "markdown",
317 "metadata": {},
279 318 "source": [
280 319 "This produces, on our polynomial ``p``, the following:"
281 320 ]
@@ -287,59 +326,53 b''
287 326 "poly2latex(p)"
288 327 ],
289 328 "language": "python",
290 "outputs": [],
291 "prompt_number": 10
292 },
293 {
294 "cell_type": "markdown",
295 "source": [
296 "Note that this did *not* produce a formated LaTeX object, because it is simply a string ",
297 "with LaTeX code. In order for this to be interpreted as a mathematical expression, it",
298 "must be properly wrapped into a Math object:"
299 ]
329 "metadata": {},
330 "outputs": []
300 331 },
301 332 {
302 333 "cell_type": "code",
303 334 "collapsed": false,
304 335 "input": [
305 "from IPython.core.display import Math",
306 "Math(poly2latex(p))"
336 "from IPython.display import Latex\n",
337 "Latex(poly2latex(p))"
307 338 ],
308 339 "language": "python",
309 "outputs": [],
310 "prompt_number": 11
340 "metadata": {},
341 "outputs": []
311 342 },
312 343 {
313 344 "cell_type": "markdown",
345 "metadata": {},
314 346 "source": [
315 "But we can configure IPython to do this automatically for us as follows. We hook into the",
316 "IPython display system and instruct it to use ``poly2latex`` for the latex mimetype, when",
317 "encountering objects of the ``Polynomial`` type defined in the",
347 "But we can configure IPython to do this automatically for us as follows. We hook into the\n",
348 "IPython display system and instruct it to use ``poly2latex`` for the latex mimetype, when\n",
349 "encountering objects of the ``Polynomial`` type defined in the\n",
318 350 "``numpy.polynomial.polynomial`` module:"
319 351 ]
320 352 },
321 353 {
322 354 "cell_type": "code",
323 "collapsed": true,
355 "collapsed": false,
324 356 "input": [
325 "ip = get_ipython()",
326 "latex_formatter = ip.display_formatter.formatters['text/latex']",
327 "latex_formatter.for_type_by_name('numpy.polynomial.polynomial',",
357 "ip = get_ipython()\n",
358 "latex_formatter = ip.display_formatter.formatters['text/latex']\n",
359 "latex_formatter.for_type_by_name('numpy.polynomial.polynomial',\n",
328 360 " 'Polynomial', poly2latex)"
329 361 ],
330 362 "language": "python",
331 "outputs": [],
332 "prompt_number": 12
363 "metadata": {},
364 "outputs": []
333 365 },
334 366 {
335 367 "cell_type": "markdown",
368 "metadata": {},
336 369 "source": [
337 "For more examples on how to use the above system, and how to bundle similar print functions",
338 "into a convenient IPython extension, see the ``IPython/extensions/sympyprinting.py`` file. ",
339 "The machinery that defines the display system is in the ``display.py`` and ``displaypub.py`` ",
340 "files in ``IPython/core``.",
341 "",
342 "Once our special printer has been loaded, all polynomials will be represented by their ",
370 "For more examples on how to use the above system, and how to bundle similar print functions\n",
371 "into a convenient IPython extension, see the ``IPython/extensions/sympyprinting.py`` file. \n",
372 "The machinery that defines the display system is in the ``display.py`` and ``displaypub.py`` \n",
373 "files in ``IPython/core``.\n",
374 "\n",
375 "Once our special printer has been loaded, all polynomials will be represented by their \n",
343 376 "mathematical form instead:"
344 377 ]
345 378 },
@@ -350,29 +383,22 b''
350 383 "p"
351 384 ],
352 385 "language": "python",
353 "outputs": [],
354 "prompt_number": 13
386 "metadata": {},
387 "outputs": []
355 388 },
356 389 {
357 390 "cell_type": "code",
358 391 "collapsed": false,
359 392 "input": [
360 "p2 = np.polynomial.Polynomial([-20, 71, -15, 1])",
393 "p2 = np.polynomial.Polynomial([-20, 71, -15, 1])\n",
361 394 "p2"
362 395 ],
363 396 "language": "python",
364 "outputs": [],
365 "prompt_number": 14
366 },
367 {
368 "cell_type": "code",
369 "collapsed": true,
370 "input": [],
371 "language": "python",
372 "outputs": [],
373 "prompt_number": 14
397 "metadata": {},
398 "outputs": []
374 399 }
375 ]
400 ],
401 "metadata": {}
376 402 }
377 403 ]
378 404 } No newline at end of file
@@ -3,124 +3,137 b''
3 3 "name": "formatting"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "markdown",
12 "metadata": {},
11 13 "source": [
12 "# Examples of basic formatting in the notebook",
13 "",
14 "Normal and formatted text cells such as this one use the ",
15 "[Markdown](http://daringfireball.net/projects/markdown/basics) syntax.",
16 "",
17 "",
18 "# Title (h1)",
19 "",
20 "## Heading (h2)",
21 "",
22 "### Heading (h3)",
23 "",
24 "Here is a paragraph of text.",
25 "",
26 "* One.",
27 " - Sublist",
28 " - Here we go",
29 " - Sublist",
30 " - Here we go",
31 " - Here we go",
32 "* Two.",
33 " - Sublist",
34 "* Three.",
35 " - Sublist",
36 "",
37 "Now another list:",
38 "",
39 "---",
40 "",
41 "1. Here we go",
42 " 1. Sublist",
43 " 2. Sublist",
44 "2. There we go",
45 "3. Now this",
46 "",
47 "And another paragraph.",
48 "",
49 "### Heading (h3)",
50 "",
51 "#### Heading (h4)",
52 "",
53 "##### Heading (h5)",
54 "",
55 "###### Heading (h6)",
56 "",
14 "# Examples of basic formatting in the notebook\n",
15 "\n",
16 "Normal and formatted text cells such as this one use the \n",
17 "[Markdown](http://daringfireball.net/projects/markdown/basics) syntax.\n",
18 "\n",
19 "\n",
20 "# Title (h1)\n",
21 "\n",
22 "## Heading (h2)\n",
23 "\n",
24 "### Heading (h3)\n",
25 "\n",
26 "Here is a paragraph of text.\n",
27 "\n",
28 "* One.\n",
29 " - Sublist\n",
30 " - Here we go\n",
31 " - Sublist\n",
32 " - Here we go\n",
33 " - Here we go\n",
34 "* Two.\n",
35 " - Sublist\n",
36 "* Three.\n",
37 " - Sublist\n",
38 "\n",
39 "Now another list:\n",
40 "\n",
41 "---\n",
42 "\n",
43 "1. Here we go\n",
44 " 1. Sublist\n",
45 " 2. Sublist\n",
46 "2. There we go\n",
47 "3. Now this\n",
48 "\n",
49 "And another paragraph.\n",
50 "\n",
51 "### Heading (h3)\n",
52 "\n",
53 "#### Heading (h4)\n",
54 "\n",
55 "##### Heading (h5)\n",
56 "\n",
57 "###### Heading (h6)\n",
58 "\n",
57 59 "## Heading (h2)"
58 60 ]
59 61 },
60 62 {
61 63 "cell_type": "markdown",
64 "metadata": {},
62 65 "source": [
63 "# Heading (h1)",
64 "",
65 "## Heading (h2)",
66 "",
67 "### Heading (h3)",
68 "",
69 "#### Heading (h4)",
70 "",
71 "##### Heading (h5)",
72 "",
73 "###### Heading (h6)",
74 "",
75 "Now for a simple code example:",
76 "",
77 " for i in range(10):",
78 " print i",
79 "",
66 "# Heading (h1)\n",
67 "\n",
68 "## Heading (h2)\n",
69 "\n",
70 "### Heading (h3)\n",
71 "\n",
72 "#### Heading (h4)\n",
73 "\n",
74 "##### Heading (h5)\n",
75 "\n",
76 "###### Heading (h6)\n",
77 "\n",
78 "Now for a simple code example:\n",
79 "\n",
80 " for i in range(10):\n",
81 " print i\n",
82 "\n",
80 83 "Now more text"
81 84 ]
82 85 },
83 86 {
84 "cell_type": "markdown",
87 "cell_type": "heading",
88 "level": 1,
89 "metadata": {},
85 90 "source": [
86 "## Heading (h2)",
87 "",
88 "Here is text.",
89 "",
90 "> This is a *block* quote. This is a block quote. This is a block quote. ",
91 "> This is a **block** quote. This is a block quote. This is a block quote. ",
92 "> This is a `block` quote. This is a block quote. This is a block quote. ",
93 "> This is a block quote. This is a block quote. This is a block quote. ",
94 "> This is a block quote. This is a block quote. This is a block quote. ",
95 "> This is a block quote. This is a block quote. This is a block quote. ",
96 "",
97 "Here is text",
98 "",
99 "<table>",
100 "<tr>",
101 "<th>Header 1</th>",
102 "<th>Header 2</th>",
103 "</tr>",
104 "<tr>",
105 "<td>row 1, cell 1</td>",
106 "<td>row 1, cell 2</td>",
107 "</tr>",
108 "<tr>",
109 "<td>row 2, cell 1</td>",
110 "<td>row 2, cell 2</td>",
111 "</tr>",
112 "</table>"
91 "This is a Heading Cell (level 1)"
92 ]
93 },
94 {
95 "cell_type": "heading",
96 "level": 4,
97 "metadata": {},
98 "source": [
99 "This is a Heading Cell (level 4)"
113 100 ]
114 101 },
115 102 {
116 "cell_type": "code",
117 "collapsed": true,
118 "input": [],
119 "language": "python",
120 "outputs": [],
121 "prompt_number": "&nbsp;"
103 "cell_type": "markdown",
104 "metadata": {},
105 "source": [
106 "## Heading (h2)\n",
107 "\n",
108 "Here is text.\n",
109 "\n",
110 "> This is a *block* quote. This is a block quote. This is a block quote. \n",
111 "> This is a **block** quote. This is a block quote. This is a block quote. \n",
112 "> This is a `block` quote. This is a block quote. This is a block quote. \n",
113 "> This is a block quote. This is a block quote. This is a block quote. \n",
114 "> This is a block quote. This is a block quote. This is a block quote. \n",
115 "> This is a block quote. This is a block quote. This is a block quote. \n",
116 "\n",
117 "Here is text\n",
118 "\n",
119 "<table>\n",
120 "<tr>\n",
121 "<th>Header 1</th>\n",
122 "<th>Header 2</th>\n",
123 "</tr>\n",
124 "<tr>\n",
125 "<td>row 1, cell 1</td>\n",
126 "<td>row 1, cell 2</td>\n",
127 "</tr>\n",
128 "<tr>\n",
129 "<td>row 2, cell 1</td>\n",
130 "<td>row 2, cell 2</td>\n",
131 "</tr>\n",
132 "</table>"
133 ]
122 134 }
123 ]
135 ],
136 "metadata": {}
124 137 }
125 138 ]
126 139 } No newline at end of file
@@ -3,12 +3,14 b''
3 3 "name": "octavemagic_extension"
4 4 },
5 5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "heading",
11 12 "level": 1,
13 "metadata": {},
12 14 "source": [
13 15 "octavemagic: Octave inside IPython"
14 16 ]
@@ -16,57 +18,65 b''
16 18 {
17 19 "cell_type": "heading",
18 20 "level": 2,
21 "metadata": {},
19 22 "source": [
20 23 "Installation"
21 24 ]
22 25 },
23 26 {
24 27 "cell_type": "markdown",
28 "metadata": {},
25 29 "source": [
26 "The `octavemagic` extension provides the ability to interact with Octave. It depends on the `oct2py` and `h5py` packages,",
27 "which may be installed using `easy_install`.",
28 "",
30 "The `octavemagic` extension provides the ability to interact with Octave. It depends on the `oct2py` and `h5py` packages,\n",
31 "which may be installed using `easy_install`.\n",
32 "\n",
29 33 "To enable the extension, load it as follows:"
30 34 ]
31 35 },
32 36 {
33 37 "cell_type": "code",
38 "collapsed": false,
34 39 "input": [
35 40 "%load_ext octavemagic"
36 41 ],
37 42 "language": "python",
43 "metadata": {},
38 44 "outputs": [],
39 45 "prompt_number": 18
40 46 },
41 47 {
42 48 "cell_type": "heading",
43 49 "level": 2,
50 "metadata": {},
44 51 "source": [
45 52 "Overview"
46 53 ]
47 54 },
48 55 {
49 56 "cell_type": "markdown",
57 "metadata": {},
50 58 "source": [
51 "Loading the extension enables three magic functions: `%octave`, `%octave_push`, and `%octave_pull`.",
52 "",
53 "The first is for executing one or more lines of Octave, while the latter allow moving variables between the Octave and Python workspace.",
59 "Loading the extension enables three magic functions: `%octave`, `%octave_push`, and `%octave_pull`.\n",
60 "\n",
61 "The first is for executing one or more lines of Octave, while the latter allow moving variables between the Octave and Python workspace.\n",
54 62 "Here you see an example of how to execute a single line of Octave, and how to transfer the generated value back to Python:"
55 63 ]
56 64 },
57 65 {
58 66 "cell_type": "code",
67 "collapsed": false,
59 68 "input": [
60 "x = %octave [1 2; 3 4];",
69 "x = %octave [1 2; 3 4];\n",
61 70 "x"
62 71 ],
63 72 "language": "python",
73 "metadata": {},
64 74 "outputs": [
65 75 {
66 76 "output_type": "pyout",
67 77 "prompt_number": 19,
68 78 "text": [
69 "array([[ 1., 2.],",
79 "array([[ 1., 2.],\n",
70 80 " [ 3., 4.]])"
71 81 ]
72 82 }
@@ -75,15 +85,17 b''
75 85 },
76 86 {
77 87 "cell_type": "code",
88 "collapsed": false,
78 89 "input": [
79 "a = [1, 2, 3]",
80 "",
81 "%octave_push a",
82 "%octave a = a * 2;",
83 "%octave_pull a",
90 "a = [1, 2, 3]\n",
91 "\n",
92 "%octave_push a\n",
93 "%octave a = a * 2;\n",
94 "%octave_pull a\n",
84 95 "a"
85 96 ],
86 97 "language": "python",
98 "metadata": {},
87 99 "outputs": [
88 100 {
89 101 "output_type": "pyout",
@@ -97,33 +109,38 b''
97 109 },
98 110 {
99 111 "cell_type": "markdown",
112 "metadata": {},
100 113 "source": [
101 "When using the cell magic, `%%octave` (note the double `%`), multiple lines of Octave can be executed together. Unlike",
114 "When using the cell magic, `%%octave` (note the double `%`), multiple lines of Octave can be executed together. Unlike\n",
102 115 "with the single cell magic, no value is returned, so we use the `-i` and `-o` flags to specify input and output variables."
103 116 ]
104 117 },
105 118 {
106 119 "cell_type": "code",
120 "collapsed": false,
107 121 "input": [
108 "%%octave -i x -o y",
122 "%%octave -i x -o y\n",
109 123 "y = x + 3;"
110 124 ],
111 125 "language": "python",
126 "metadata": {},
112 127 "outputs": [],
113 128 "prompt_number": 21
114 129 },
115 130 {
116 131 "cell_type": "code",
132 "collapsed": false,
117 133 "input": [
118 134 "y"
119 135 ],
120 136 "language": "python",
137 "metadata": {},
121 138 "outputs": [
122 139 {
123 140 "output_type": "pyout",
124 141 "prompt_number": 22,
125 142 "text": [
126 "array([[ 4., 5.],",
143 "array([[ 4., 5.],\n",
127 144 " [ 6., 7.]])"
128 145 ]
129 146 }
@@ -133,28 +150,32 b''
133 150 {
134 151 "cell_type": "heading",
135 152 "level": 2,
153 "metadata": {},
136 154 "source": [
137 155 "Plotting"
138 156 ]
139 157 },
140 158 {
141 159 "cell_type": "markdown",
160 "metadata": {},
142 161 "source": [
143 162 "Plot output is automatically captured and displayed, and using the `-f` flag you may choose its format (currently, `png` and `svg` are supported)."
144 163 ]
145 164 },
146 165 {
147 166 "cell_type": "code",
167 "collapsed": false,
148 168 "input": [
149 "%%octave -f svg",
150 "",
151 "p = [12 -2.5 -8 -0.1 8];",
152 "x = 0:0.01:1;",
153 "",
154 "polyout(p, 'x')",
169 "%%octave -f svg\n",
170 "\n",
171 "p = [12 -2.5 -8 -0.1 8];\n",
172 "x = 0:0.01:1;\n",
173 "\n",
174 "polyout(p, 'x')\n",
155 175 "plot(x, polyval(p, x));"
156 176 ],
157 177 "language": "python",
178 "metadata": {},
158 179 "outputs": [
159 180 {
160 181 "output_type": "display_data",
@@ -165,111 +186,111 b''
165 186 {
166 187 "output_type": "display_data",
167 188 "svg": [
168 "<svg height=\"240px\" viewBox=\"0 0 192 115\" width=\"400px\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">",
169 "",
170 "<desc>Produced by GNUPLOT 4.4 patchlevel 0 </desc>",
171 "",
172 "<defs>",
173 "",
174 "\t<circle id=\"gpDot\" r=\"0.5\" stroke-width=\"0.5\"/>",
175 "\t<path d=\"M-1,0 h2 M0,-1 v2\" id=\"gpPt0\" stroke=\"currentColor\" stroke-width=\"0.333\"/>",
176 "\t<path d=\"M-1,-1 L1,1 M1,-1 L-1,1\" id=\"gpPt1\" stroke=\"currentColor\" stroke-width=\"0.333\"/>",
177 "\t<path d=\"M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1\" id=\"gpPt2\" stroke=\"currentColor\" stroke-width=\"0.333\"/>",
178 "\t<rect height=\"2\" id=\"gpPt3\" stroke=\"currentColor\" stroke-width=\"0.333\" width=\"2\" x=\"-1\" y=\"-1\"/>",
179 "\t<rect fill=\"currentColor\" height=\"2\" id=\"gpPt4\" stroke=\"currentColor\" stroke-width=\"0.333\" width=\"2\" x=\"-1\" y=\"-1\"/>",
180 "\t<circle cx=\"0\" cy=\"0\" id=\"gpPt5\" r=\"1\" stroke=\"currentColor\" stroke-width=\"0.333\"/>",
181 "\t<use fill=\"currentColor\" id=\"gpPt6\" stroke=\"none\" xlink:href=\"#gpPt5\"/>",
182 "\t<path d=\"M0,-1.33 L-1.33,0.67 L1.33,0.67 z\" id=\"gpPt7\" stroke=\"currentColor\" stroke-width=\"0.333\"/>",
183 "\t<use fill=\"currentColor\" id=\"gpPt8\" stroke=\"none\" xlink:href=\"#gpPt7\"/>",
184 "\t<use id=\"gpPt9\" stroke=\"currentColor\" transform=\"rotate(180)\" xlink:href=\"#gpPt7\"/>",
185 "\t<use fill=\"currentColor\" id=\"gpPt10\" stroke=\"none\" xlink:href=\"#gpPt9\"/>",
186 "\t<use id=\"gpPt11\" stroke=\"currentColor\" transform=\"rotate(45)\" xlink:href=\"#gpPt3\"/>",
187 "\t<use fill=\"currentColor\" id=\"gpPt12\" stroke=\"none\" xlink:href=\"#gpPt11\"/>",
188 "</defs>",
189 "<g style=\"fill:none; color:white; stroke:currentColor; stroke-width:1.00; stroke-linecap:butt; stroke-linejoin:miter\">",
190 "</g>",
191 "<g style=\"fill:none; color:white; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">",
192 "</g>",
193 "<g style=\"fill:none; color:black; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">",
194 "\t<path d=\"M36.4,91.2 L44.8,91.2 M177.9,91.2 L169.5,91.2 \"/>",
195 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,94.2)\">",
196 "\t\t<text><tspan>6</tspan>",
197 "\t\t</text>",
198 "\t</g>",
199 "\t<path d=\"M36.4,79.8 L44.8,79.8 M177.9,79.8 L169.5,79.8 \"/>",
200 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,82.8)\">",
201 "\t\t<text><tspan>6.5</tspan>",
202 "\t\t</text>",
203 "\t</g>",
204 "\t<path d=\"M36.4,68.4 L44.8,68.4 M177.9,68.4 L169.5,68.4 \"/>",
205 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,71.4)\">",
206 "\t\t<text><tspan>7</tspan>",
207 "\t\t</text>",
208 "\t</g>",
209 "\t<path d=\"M36.4,57.0 L44.8,57.0 M177.9,57.0 L169.5,57.0 \"/>",
210 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,60.0)\">",
211 "\t\t<text><tspan>7.5</tspan>",
212 "\t\t</text>",
213 "\t</g>",
214 "\t<path d=\"M36.4,45.5 L44.8,45.5 M177.9,45.5 L169.5,45.5 \"/>",
215 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,48.5)\">",
216 "\t\t<text><tspan>8</tspan>",
217 "\t\t</text>",
218 "\t</g>",
219 "\t<path d=\"M36.4,34.1 L44.8,34.1 M177.9,34.1 L169.5,34.1 \"/>",
220 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,37.1)\">",
221 "\t\t<text><tspan>8.5</tspan>",
222 "\t\t</text>",
223 "\t</g>",
224 "\t<path d=\"M36.4,22.7 L44.8,22.7 M177.9,22.7 L169.5,22.7 \"/>",
225 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,25.7)\">",
226 "\t\t<text><tspan>9</tspan>",
227 "\t\t</text>",
228 "\t</g>",
229 "\t<path d=\"M36.4,11.3 L44.8,11.3 M177.9,11.3 L169.5,11.3 \"/>",
230 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,14.3)\">",
231 "\t\t<text><tspan>9.5</tspan>",
232 "\t\t</text>",
233 "\t</g>",
234 "\t<path d=\"M36.4,91.2 L36.4,82.8 M36.4,11.3 L36.4,19.7 \"/>",
235 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(36.4,106.2)\">",
236 "\t\t<text><tspan>0</tspan>",
237 "\t\t</text>",
238 "\t</g>",
239 "\t<path d=\"M64.7,91.2 L64.7,82.8 M64.7,11.3 L64.7,19.7 \"/>",
240 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(64.7,106.2)\">",
241 "\t\t<text><tspan>0.2</tspan>",
242 "\t\t</text>",
243 "\t</g>",
244 "\t<path d=\"M93.0,91.2 L93.0,82.8 M93.0,11.3 L93.0,19.7 \"/>",
245 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(93.0,106.2)\">",
246 "\t\t<text><tspan>0.4</tspan>",
247 "\t\t</text>",
248 "\t</g>",
249 "\t<path d=\"M121.3,91.2 L121.3,82.8 M121.3,11.3 L121.3,19.7 \"/>",
250 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(121.3,106.2)\">",
251 "\t\t<text><tspan>0.6</tspan>",
252 "\t\t</text>",
253 "\t</g>",
254 "\t<path d=\"M149.6,91.2 L149.6,82.8 M149.6,11.3 L149.6,19.7 \"/>",
255 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(149.6,106.2)\">",
256 "\t\t<text><tspan>0.8</tspan>",
257 "\t\t</text>",
258 "\t</g>",
259 "\t<path d=\"M177.9,91.2 L177.9,82.8 M177.9,11.3 L177.9,19.7 \"/>",
260 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(177.9,106.2)\">",
261 "\t\t<text><tspan>1</tspan>",
262 "\t\t</text>",
263 "\t</g>",
264 "\t<path d=\"M36.4,11.3 L36.4,91.2 L177.9,91.2 L177.9,11.3 L36.4,11.3 Z \"/>",
265 "</g>",
266 "\t<a xlink:title=\"Plot #1\">",
267 "<g style=\"fill:none; color:red; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">",
268 "\t<path d=\"M36.4,45.5 L37.8,45.6 L39.2,45.7 L40.6,45.8 L42.1,45.9 L43.5,46.1 L44.9,46.3 L46.3,46.6 L47.7,46.9 L49.1,47.3 L50.6,47.6 L52.0,48.0 L53.4,48.5 L54.8,49.0 L56.2,49.5 L57.6,50.0 L59.0,50.6 L60.5,51.3 L61.9,51.9 L63.3,52.6 L64.7,53.3 L66.1,54.1 L67.5,54.9 L68.9,55.7 L70.4,56.5 L71.8,57.3 L73.2,58.2 L74.6,59.1 L76.0,60.1 L77.4,61.0 L78.9,62.0 L80.3,63.0 L81.7,64.0 L83.1,65.0 L84.5,66.0 L85.9,67.0 L87.3,68.1 L88.8,69.1 L90.2,70.2 L91.6,71.3 L93.0,72.3 L94.4,73.4 L95.8,74.4 L97.2,75.5 L98.7,76.5 L100.1,77.5 L101.5,78.5 L102.9,79.5 L104.3,80.5 L105.7,81.4 L107.2,82.4 L108.6,83.2 L110.0,84.1 L111.4,84.9 L112.8,85.7 L114.2,86.5 L115.6,87.2 L117.1,87.8 L118.5,88.4 L119.9,89.0 L121.3,89.5 L122.7,89.9 L124.1,90.3 L125.5,90.6 L127.0,90.8 L128.4,91.0 L129.8,91.0 L131.2,91.0 L132.6,90.9 L134.0,90.7 L135.5,90.4 L136.9,90.0 L138.3,89.5 L139.7,88.9 L141.1,88.2 L142.5,87.4 L143.9,86.4 L145.4,85.3 L146.8,84.1 L148.2,82.8 L149.6,81.3 L151.0,79.6 L152.4,77.8 L153.8,75.9 L155.3,73.8 L156.7,71.5 L158.1,69.0 L159.5,66.4 L160.9,63.6 L162.3,60.6 L163.8,57.4 L165.2,54.0 L166.6,50.4 L168.0,46.6 L169.4,42.6 L170.8,38.3 L172.2,33.9 L173.7,29.2 L175.1,24.2 L176.5,19.0 L177.9,13.6 \" stroke=\"rgb( 0, 0, 255)\"/>",
269 "</g>",
270 "\t</a>",
271 "<g style=\"fill:none; color:black; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">",
272 "</g>",
189 "<svg height=\"240px\" viewBox=\"0 0 192 115\" width=\"400px\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
190 "\n",
191 "<desc>Produced by GNUPLOT 4.4 patchlevel 0 </desc>\n",
192 "\n",
193 "<defs>\n",
194 "\n",
195 "\t<circle id=\"gpDot\" r=\"0.5\" stroke-width=\"0.5\"/>\n",
196 "\t<path d=\"M-1,0 h2 M0,-1 v2\" id=\"gpPt0\" stroke=\"currentColor\" stroke-width=\"0.333\"/>\n",
197 "\t<path d=\"M-1,-1 L1,1 M1,-1 L-1,1\" id=\"gpPt1\" stroke=\"currentColor\" stroke-width=\"0.333\"/>\n",
198 "\t<path d=\"M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1\" id=\"gpPt2\" stroke=\"currentColor\" stroke-width=\"0.333\"/>\n",
199 "\t<rect height=\"2\" id=\"gpPt3\" stroke=\"currentColor\" stroke-width=\"0.333\" width=\"2\" x=\"-1\" y=\"-1\"/>\n",
200 "\t<rect fill=\"currentColor\" height=\"2\" id=\"gpPt4\" stroke=\"currentColor\" stroke-width=\"0.333\" width=\"2\" x=\"-1\" y=\"-1\"/>\n",
201 "\t<circle cx=\"0\" cy=\"0\" id=\"gpPt5\" r=\"1\" stroke=\"currentColor\" stroke-width=\"0.333\"/>\n",
202 "\t<use fill=\"currentColor\" id=\"gpPt6\" stroke=\"none\" xlink:href=\"#gpPt5\"/>\n",
203 "\t<path d=\"M0,-1.33 L-1.33,0.67 L1.33,0.67 z\" id=\"gpPt7\" stroke=\"currentColor\" stroke-width=\"0.333\"/>\n",
204 "\t<use fill=\"currentColor\" id=\"gpPt8\" stroke=\"none\" xlink:href=\"#gpPt7\"/>\n",
205 "\t<use id=\"gpPt9\" stroke=\"currentColor\" transform=\"rotate(180)\" xlink:href=\"#gpPt7\"/>\n",
206 "\t<use fill=\"currentColor\" id=\"gpPt10\" stroke=\"none\" xlink:href=\"#gpPt9\"/>\n",
207 "\t<use id=\"gpPt11\" stroke=\"currentColor\" transform=\"rotate(45)\" xlink:href=\"#gpPt3\"/>\n",
208 "\t<use fill=\"currentColor\" id=\"gpPt12\" stroke=\"none\" xlink:href=\"#gpPt11\"/>\n",
209 "</defs>\n",
210 "<g style=\"fill:none; color:white; stroke:currentColor; stroke-width:1.00; stroke-linecap:butt; stroke-linejoin:miter\">\n",
211 "</g>\n",
212 "<g style=\"fill:none; color:white; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">\n",
213 "</g>\n",
214 "<g style=\"fill:none; color:black; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">\n",
215 "\t<path d=\"M36.4,91.2 L44.8,91.2 M177.9,91.2 L169.5,91.2 \"/>\n",
216 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,94.2)\">\n",
217 "\t\t<text><tspan>6</tspan>\n",
218 "\t\t</text>\n",
219 "\t</g>\n",
220 "\t<path d=\"M36.4,79.8 L44.8,79.8 M177.9,79.8 L169.5,79.8 \"/>\n",
221 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,82.8)\">\n",
222 "\t\t<text><tspan>6.5</tspan>\n",
223 "\t\t</text>\n",
224 "\t</g>\n",
225 "\t<path d=\"M36.4,68.4 L44.8,68.4 M177.9,68.4 L169.5,68.4 \"/>\n",
226 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,71.4)\">\n",
227 "\t\t<text><tspan>7</tspan>\n",
228 "\t\t</text>\n",
229 "\t</g>\n",
230 "\t<path d=\"M36.4,57.0 L44.8,57.0 M177.9,57.0 L169.5,57.0 \"/>\n",
231 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,60.0)\">\n",
232 "\t\t<text><tspan>7.5</tspan>\n",
233 "\t\t</text>\n",
234 "\t</g>\n",
235 "\t<path d=\"M36.4,45.5 L44.8,45.5 M177.9,45.5 L169.5,45.5 \"/>\n",
236 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,48.5)\">\n",
237 "\t\t<text><tspan>8</tspan>\n",
238 "\t\t</text>\n",
239 "\t</g>\n",
240 "\t<path d=\"M36.4,34.1 L44.8,34.1 M177.9,34.1 L169.5,34.1 \"/>\n",
241 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,37.1)\">\n",
242 "\t\t<text><tspan>8.5</tspan>\n",
243 "\t\t</text>\n",
244 "\t</g>\n",
245 "\t<path d=\"M36.4,22.7 L44.8,22.7 M177.9,22.7 L169.5,22.7 \"/>\n",
246 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,25.7)\">\n",
247 "\t\t<text><tspan>9</tspan>\n",
248 "\t\t</text>\n",
249 "\t</g>\n",
250 "\t<path d=\"M36.4,11.3 L44.8,11.3 M177.9,11.3 L169.5,11.3 \"/>\n",
251 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:end\" transform=\"translate(30.8,14.3)\">\n",
252 "\t\t<text><tspan>9.5</tspan>\n",
253 "\t\t</text>\n",
254 "\t</g>\n",
255 "\t<path d=\"M36.4,91.2 L36.4,82.8 M36.4,11.3 L36.4,19.7 \"/>\n",
256 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(36.4,106.2)\">\n",
257 "\t\t<text><tspan>0</tspan>\n",
258 "\t\t</text>\n",
259 "\t</g>\n",
260 "\t<path d=\"M64.7,91.2 L64.7,82.8 M64.7,11.3 L64.7,19.7 \"/>\n",
261 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(64.7,106.2)\">\n",
262 "\t\t<text><tspan>0.2</tspan>\n",
263 "\t\t</text>\n",
264 "\t</g>\n",
265 "\t<path d=\"M93.0,91.2 L93.0,82.8 M93.0,11.3 L93.0,19.7 \"/>\n",
266 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(93.0,106.2)\">\n",
267 "\t\t<text><tspan>0.4</tspan>\n",
268 "\t\t</text>\n",
269 "\t</g>\n",
270 "\t<path d=\"M121.3,91.2 L121.3,82.8 M121.3,11.3 L121.3,19.7 \"/>\n",
271 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(121.3,106.2)\">\n",
272 "\t\t<text><tspan>0.6</tspan>\n",
273 "\t\t</text>\n",
274 "\t</g>\n",
275 "\t<path d=\"M149.6,91.2 L149.6,82.8 M149.6,11.3 L149.6,19.7 \"/>\n",
276 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(149.6,106.2)\">\n",
277 "\t\t<text><tspan>0.8</tspan>\n",
278 "\t\t</text>\n",
279 "\t</g>\n",
280 "\t<path d=\"M177.9,91.2 L177.9,82.8 M177.9,11.3 L177.9,19.7 \"/>\n",
281 "\t<g style=\"stroke:none; fill:rgb(0,0,0); font-family:{}; font-size:10.00pt; text-anchor:middle\" transform=\"translate(177.9,106.2)\">\n",
282 "\t\t<text><tspan>1</tspan>\n",
283 "\t\t</text>\n",
284 "\t</g>\n",
285 "\t<path d=\"M36.4,11.3 L36.4,91.2 L177.9,91.2 L177.9,11.3 L36.4,11.3 Z \"/>\n",
286 "</g>\n",
287 "\t<a xlink:title=\"Plot #1\">\n",
288 "<g style=\"fill:none; color:red; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">\n",
289 "\t<path d=\"M36.4,45.5 L37.8,45.6 L39.2,45.7 L40.6,45.8 L42.1,45.9 L43.5,46.1 L44.9,46.3 L46.3,46.6 L47.7,46.9 L49.1,47.3 L50.6,47.6 L52.0,48.0 L53.4,48.5 L54.8,49.0 L56.2,49.5 L57.6,50.0 L59.0,50.6 L60.5,51.3 L61.9,51.9 L63.3,52.6 L64.7,53.3 L66.1,54.1 L67.5,54.9 L68.9,55.7 L70.4,56.5 L71.8,57.3 L73.2,58.2 L74.6,59.1 L76.0,60.1 L77.4,61.0 L78.9,62.0 L80.3,63.0 L81.7,64.0 L83.1,65.0 L84.5,66.0 L85.9,67.0 L87.3,68.1 L88.8,69.1 L90.2,70.2 L91.6,71.3 L93.0,72.3 L94.4,73.4 L95.8,74.4 L97.2,75.5 L98.7,76.5 L100.1,77.5 L101.5,78.5 L102.9,79.5 L104.3,80.5 L105.7,81.4 L107.2,82.4 L108.6,83.2 L110.0,84.1 L111.4,84.9 L112.8,85.7 L114.2,86.5 L115.6,87.2 L117.1,87.8 L118.5,88.4 L119.9,89.0 L121.3,89.5 L122.7,89.9 L124.1,90.3 L125.5,90.6 L127.0,90.8 L128.4,91.0 L129.8,91.0 L131.2,91.0 L132.6,90.9 L134.0,90.7 L135.5,90.4 L136.9,90.0 L138.3,89.5 L139.7,88.9 L141.1,88.2 L142.5,87.4 L143.9,86.4 L145.4,85.3 L146.8,84.1 L148.2,82.8 L149.6,81.3 L151.0,79.6 L152.4,77.8 L153.8,75.9 L155.3,73.8 L156.7,71.5 L158.1,69.0 L159.5,66.4 L160.9,63.6 L162.3,60.6 L163.8,57.4 L165.2,54.0 L166.6,50.4 L168.0,46.6 L169.4,42.6 L170.8,38.3 L172.2,33.9 L173.7,29.2 L175.1,24.2 L176.5,19.0 L177.9,13.6 \" stroke=\"rgb( 0, 0, 255)\"/>\n",
290 "</g>\n",
291 "\t</a>\n",
292 "<g style=\"fill:none; color:black; stroke:currentColor; stroke-width:0.50; stroke-linecap:butt; stroke-linejoin:miter\">\n",
293 "</g>\n",
273 294 "</svg>"
274 295 ]
275 296 }
@@ -278,21 +299,24 b''
278 299 },
279 300 {
280 301 "cell_type": "markdown",
302 "metadata": {},
281 303 "source": [
282 304 "The plot size is adjusted using the `-s` flag:"
283 305 ]
284 306 },
285 307 {
286 308 "cell_type": "code",
309 "collapsed": false,
287 310 "input": [
288 "%%octave -s 500,500",
289 "",
290 "# butterworth filter, order 2, cutoff pi/2 radians",
291 "b = [0.292893218813452 0.585786437626905 0.292893218813452];",
292 "a = [1 0 0.171572875253810];",
311 "%%octave -s 500,500\n",
312 "\n",
313 "# butterworth filter, order 2, cutoff pi/2 radians\n",
314 "b = [0.292893218813452 0.585786437626905 0.292893218813452];\n",
315 "a = [1 0 0.171572875253810];\n",
293 316 "freqz(b, a, 32);"
294 317 ],
295 318 "language": "python",
319 "metadata": {},
296 320 "outputs": [
297 321 {
298 322 "output_type": "display_data",
@@ -303,18 +327,20 b''
303 327 },
304 328 {
305 329 "cell_type": "code",
330 "collapsed": false,
306 331 "input": [
307 "%%octave -s 600,200 -f png",
308 "",
309 "subplot(121);",
310 "[x, y] = meshgrid(0:0.1:3);",
311 "r = sin(x - 0.5).^2 + cos(y - 0.5).^2;",
312 "surf(x, y, r);",
313 "",
314 "subplot(122);",
332 "%%octave -s 600,200 -f png\n",
333 "\n",
334 "subplot(121);\n",
335 "[x, y] = meshgrid(0:0.1:3);\n",
336 "r = sin(x - 0.5).^2 + cos(y - 0.5).^2;\n",
337 "surf(x, y, r);\n",
338 "\n",
339 "subplot(122);\n",
315 340 "sombrero()"
316 341 ],
317 342 "language": "python",
343 "metadata": {},
318 344 "outputs": [
319 345 {
320 346 "output_type": "display_data",
@@ -326,17 +352,20 b''
326 352 {
327 353 "cell_type": "heading",
328 354 "level": 2,
355 "metadata": {},
329 356 "source": [
330 357 "Future work"
331 358 ]
332 359 },
333 360 {
334 361 "cell_type": "markdown",
362 "metadata": {},
335 363 "source": [
336 364 "After the next release of `oct2py`, we'll add the ability to interrupt/kill the current Octave session without restarting the Python kernel."
337 365 ]
338 366 }
339 ]
367 ],
368 "metadata": {}
340 369 }
341 370 ]
342 371 } No newline at end of file
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now