Show More
This diff has been collapsed as it changes many lines, (511 lines changed) Show them Hide them | |||||
@@ -0,0 +1,511 b'' | |||||
|
1 | # A brief tour of the IPython notebook | |||
|
2 | ||||
|
3 | This document will give you a brief tour of the capabilities of the IPython notebook. | |||
|
4 | You can view its contents by scrolling around, or execute each cell by typing `Shift-Enter`. | |||
|
5 | After you conclude this brief high-level tour, you should read the accompanying notebook | |||
|
6 | titled `01_notebook_introduction`, which takes a more step-by-step approach to the features of the | |||
|
7 | system. | |||
|
8 | ||||
|
9 | The rest of the notebooks in this directory illustrate various other aspects and | |||
|
10 | capabilities of the IPython notebook; some of them may require additional libraries to be executed. | |||
|
11 | ||||
|
12 | **NOTE:** This notebook *must* be run from its own directory, so you must ``cd`` | |||
|
13 | to this directory and then start the notebook, but do *not* use the ``--notebook-dir`` | |||
|
14 | option to run it from another location. | |||
|
15 | ||||
|
16 | The first thing you need to know is that you are still controlling the same old IPython you're used to, | |||
|
17 | so things like shell aliases and magic commands still work: | |||
|
18 | ||||
|
19 | <div class="highlight"><pre><span class="n">pwd</span> | |||
|
20 | </pre></div> | |||
|
21 | ||||
|
22 | ||||
|
23 | <pre> | |||
|
24 | u'/Users/minrk/dev/ip/mine/docs/examples/notebooks' | |||
|
25 | </pre> | |||
|
26 | ||||
|
27 | ||||
|
28 | <div class="highlight"><pre><span class="n">ls</span> | |||
|
29 | </pre></div> | |||
|
30 | ||||
|
31 | ||||
|
32 | 00_notebook_tour.ipynb callbacks.ipynb python-logo.svg | |||
|
33 | 01_notebook_introduction.ipynb cython_extension.ipynb rmagic_extension.ipynb | |||
|
34 | Animations_and_Progress.ipynb display_protocol.ipynb sympy.ipynb | |||
|
35 | Capturing Output.ipynb formatting.ipynb sympy_quantum_computing.ipynb | |||
|
36 | Script Magics.ipynb octavemagic_extension.ipynb trapezoid_rule.ipynb | |||
|
37 | animation.m4v progbar.ipynb | |||
|
38 | ||||
|
39 | ||||
|
40 | <div class="highlight"><pre><span class="n">message</span> <span class="o">=</span> <span class="s">'The IPython notebook is great!'</span> | |||
|
41 | <span class="c"># note: the echo command does not run on Windows, it's a unix command.</span> | |||
|
42 | <span class="o">!</span><span class="nb">echo</span> <span class="nv">$message</span> | |||
|
43 | </pre></div> | |||
|
44 | ||||
|
45 | ||||
|
46 | The IPython notebook is great! | |||
|
47 | ||||
|
48 | ||||
|
49 | ## Plots with matplotlib | |||
|
50 | ||||
|
51 | IPython adds an 'inline' matplotlib backend, | |||
|
52 | which embeds any matplotlib figures into the notebook. | |||
|
53 | ||||
|
54 | <div class="highlight"><pre><span class="o">%</span><span class="k">pylab</span> <span class="n">inline</span> | |||
|
55 | </pre></div> | |||
|
56 | ||||
|
57 | ||||
|
58 | ||||
|
59 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
60 | For more information, type 'help(pylab)'. | |||
|
61 | ||||
|
62 | ||||
|
63 | <div class="highlight"><pre><span class="n">x</span> <span class="o">=</span> <span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="o">*</span><span class="n">pi</span><span class="p">,</span> <span class="mi">500</span><span class="p">)</span> | |||
|
64 | <span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">sin</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span><span class="p">))</span> | |||
|
65 | <span class="n">title</span><span class="p">(</span><span class="s">'A simple chirp'</span><span class="p">);</span> | |||
|
66 | </pre></div> | |||
|
67 | ||||
|
68 | ||||
|
69 | ||||
|
70 | ![](tests/ipynbref/00_notebook_tour_orig_files/00_notebook_tour_orig_fig_00.png) | |||
|
71 | ||||
|
72 | ||||
|
73 | You can paste blocks of input with prompt markers, such as those from | |||
|
74 | [the official Python tutorial](http://docs.python.org/tutorial/interpreter.html#interactive-mode) | |||
|
75 | ||||
|
76 | <div class="highlight"><pre><span class="o">>>></span> <span class="n">the_world_is_flat</span> <span class="o">=</span> <span class="mi">1</span> | |||
|
77 | <span class="o">>>></span> <span class="k">if</span> <span class="n">the_world_is_flat</span><span class="p">:</span> | |||
|
78 | <span class="o">...</span> <span class="k">print</span> <span class="s">"Be careful not to fall off!"</span> | |||
|
79 | </pre></div> | |||
|
80 | ||||
|
81 | ||||
|
82 | Be careful not to fall off! | |||
|
83 | ||||
|
84 | ||||
|
85 | Errors are shown in informative ways: | |||
|
86 | ||||
|
87 | <div class="highlight"><pre><span class="o">%</span><span class="k">run</span> <span class="n">non_existent_file</span> | |||
|
88 | </pre></div> | |||
|
89 | ||||
|
90 | ||||
|
91 | ERROR: File `u'non_existent_file.py'` not found. | |||
|
92 | ||||
|
93 | <div class="highlight"><pre><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> | |||
|
94 | <span class="n">y</span> <span class="o">=</span> <span class="mi">4</span> | |||
|
95 | <span class="n">z</span> <span class="o">=</span> <span class="n">y</span><span class="o">/</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">x</span><span class="p">)</span> | |||
|
96 | </pre></div> | |||
|
97 | ||||
|
98 | ||||
|
99 | --------------------------------------------------------------------------- | |||
|
100 | ZeroDivisionError Traceback (most recent call last) | |||
|
101 | <ipython-input-8-dc39888fd1d2> in <module>() | |||
|
102 | 1 x = 1 | |||
|
103 | 2 y = 4 | |||
|
104 | ----> 3 z = y/(1-x) | |||
|
105 | ||||
|
106 | ZeroDivisionError: integer division or modulo by zero | |||
|
107 | ||||
|
108 | ||||
|
109 | When IPython needs to display additional information (such as providing details on an object via `x?` | |||
|
110 | it will automatically invoke a pager at the bottom of the screen: | |||
|
111 | ||||
|
112 | <div class="highlight"><pre><span class="n">magic</span> | |||
|
113 | </pre></div> | |||
|
114 | ||||
|
115 | ||||
|
116 | ||||
|
117 | ## Non-blocking output of kernel | |||
|
118 | ||||
|
119 | If you execute the next cell, you will see the output arriving as it is generated, not all at the end. | |||
|
120 | ||||
|
121 | <div class="highlight"><pre><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">sys</span> | |||
|
122 | <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span> | |||
|
123 | <span class="k">print</span> <span class="n">i</span><span class="p">,</span> | |||
|
124 | <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span> | |||
|
125 | </pre></div> | |||
|
126 | ||||
|
127 | ||||
|
128 | 0 | |||
|
129 | 1 | |||
|
130 | 2 | |||
|
131 | 3 | |||
|
132 | 4 | |||
|
133 | 5 | |||
|
134 | 6 | |||
|
135 | 7 | |||
|
136 | ||||
|
137 | ||||
|
138 | ## Clean crash and restart | |||
|
139 | ||||
|
140 | We call the low-level system libc.time routine with the wrong argument via | |||
|
141 | ctypes to segfault the Python interpreter: | |||
|
142 | ||||
|
143 | <div class="highlight"><pre><span class="kn">import</span> <span class="nn">sys</span> | |||
|
144 | <span class="kn">from</span> <span class="nn">ctypes</span> <span class="kn">import</span> <span class="n">CDLL</span> | |||
|
145 | <span class="c"># This will crash a Linux or Mac system; equivalent calls can be made on Windows</span> | |||
|
146 | <span class="n">dll</span> <span class="o">=</span> <span class="s">'dylib'</span> <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s">'darwin'</span> <span class="k">else</span> <span class="s">'.so.6'</span> | |||
|
147 | <span class="n">libc</span> <span class="o">=</span> <span class="n">CDLL</span><span class="p">(</span><span class="s">"libc.</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dll</span><span class="p">)</span> | |||
|
148 | <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="c"># BOOM!!</span> | |||
|
149 | </pre></div> | |||
|
150 | ||||
|
151 | ||||
|
152 | ||||
|
153 | ## Markdown cells can contain formatted text and code | |||
|
154 | ||||
|
155 | You can *italicize*, **boldface** | |||
|
156 | ||||
|
157 | * build | |||
|
158 | * lists | |||
|
159 | ||||
|
160 | and embed code meant for illustration instead of execution in Python: | |||
|
161 | ||||
|
162 | def f(x): | |||
|
163 | """a docstring""" | |||
|
164 | return x**2 | |||
|
165 | ||||
|
166 | or other languages: | |||
|
167 | ||||
|
168 | if (i=0; i<n; i++) { | |||
|
169 | printf("hello %d\n", i); | |||
|
170 | x += 4; | |||
|
171 | } | |||
|
172 | ||||
|
173 | Courtesy of MathJax, you can include mathematical expressions both inline: | |||
|
174 | $e^{i\pi} + 1 = 0$ and displayed: | |||
|
175 | ||||
|
176 | $$e^x=\sum_{i=0}^\infty \frac{1}{i!}x^i$$ | |||
|
177 | ||||
|
178 | ## Rich displays: include anyting a browser can show | |||
|
179 | ||||
|
180 | Note that we have an actual protocol for this, see the `display_protocol` notebook for further details. | |||
|
181 | ||||
|
182 | ### Images | |||
|
183 | ||||
|
184 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">Image</span> | |||
|
185 | <span class="n">Image</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s">'../../source/_static/logo.png'</span><span class="p">)</span> | |||
|
186 | </pre></div> | |||
|
187 | ||||
|
188 | ||||
|
189 | <pre> | |||
|
190 | <IPython.core.display.Image at 0x10faeafd0> | |||
|
191 | </pre> | |||
|
192 | ||||
|
193 | ||||
|
194 | An image can also be displayed from raw data or a url | |||
|
195 | ||||
|
196 | <div class="highlight"><pre><span class="n">Image</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="s">'http://python.org/images/python-logo.gif'</span><span class="p">)</span> | |||
|
197 | </pre></div> | |||
|
198 | ||||
|
199 | ||||
|
200 | <pre> | |||
|
201 | <IPython.core.display.Image at 0x1060e7410> | |||
|
202 | </pre> | |||
|
203 | ||||
|
204 | ||||
|
205 | SVG images are also supported out of the box (since modern browsers do a good job of rendering them): | |||
|
206 | ||||
|
207 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">SVG</span> | |||
|
208 | <span class="n">SVG</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s">'python-logo.svg'</span><span class="p">)</span> | |||
|
209 | </pre></div> | |||
|
210 | ||||
|
211 | ||||
|
212 | <pre> | |||
|
213 | <IPython.core.display.SVG at 0x10fb998d0> | |||
|
214 | </pre> | |||
|
215 | ||||
|
216 | ||||
|
217 | #### Embedded vs Non-embedded Images | |||
|
218 | ||||
|
219 | As of IPython 0.13, images are embedded by default for compatibility with QtConsole, and the ability to still be displayed offline. | |||
|
220 | ||||
|
221 | Let's look at the differences: | |||
|
222 | ||||
|
223 | <div class="highlight"><pre><span class="c"># by default Image data are embedded</span> | |||
|
224 | <span class="n">Embed</span> <span class="o">=</span> <span class="n">Image</span><span class="p">(</span> <span class="s">'http://scienceview.berkeley.edu/view/images/newview.jpg'</span><span class="p">)</span> | |||
|
225 | ||||
|
226 | <span class="c"># if kwarg `url` is given, the embedding is assumed to be false</span> | |||
|
227 | <span class="n">SoftLinked</span> <span class="o">=</span> <span class="n">Image</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="s">'http://scienceview.berkeley.edu/view/images/newview.jpg'</span><span class="p">)</span> | |||
|
228 | ||||
|
229 | <span class="c"># In each case, embed can be specified explicitly with the `embed` kwarg</span> | |||
|
230 | <span class="c"># ForceEmbed = Image(url='http://scienceview.berkeley.edu/view/images/newview.jpg', embed=True)</span> | |||
|
231 | </pre></div> | |||
|
232 | ||||
|
233 | ||||
|
234 | ||||
|
235 | Today's image from a webcam at Berkeley, (at the time I created this notebook). This should also work in the Qtconsole. | |||
|
236 | Drawback is that the saved notebook will be larger, but the image will still be present offline. | |||
|
237 | ||||
|
238 | <div class="highlight"><pre><span class="n">Embed</span> | |||
|
239 | </pre></div> | |||
|
240 | ||||
|
241 | ||||
|
242 | <pre> | |||
|
243 | <IPython.core.display.Image at 0x10fb99b50> | |||
|
244 | </pre> | |||
|
245 | ||||
|
246 | ||||
|
247 | Today's image from same webcam at Berkeley, (refreshed every minutes, if you reload the notebook), visible only with an active internet connexion, that should be different from the previous one. This will not work on Qtconsole. | |||
|
248 | Notebook saved with this kind of image will be lighter and always reflect the current version of the source, but the image won't display offline. | |||
|
249 | ||||
|
250 | <div class="highlight"><pre><span class="n">SoftLinked</span> | |||
|
251 | </pre></div> | |||
|
252 | ||||
|
253 | ||||
|
254 | <pre> | |||
|
255 | <IPython.core.display.Image at 0x10fb99b10> | |||
|
256 | </pre> | |||
|
257 | ||||
|
258 | ||||
|
259 | Of course, if you re-run the all notebook, the two images will be the same again. | |||
|
260 | ||||
|
261 | ### Video | |||
|
262 | ||||
|
263 | And more exotic objects can also be displayed, as long as their representation supports | |||
|
264 | the IPython display protocol. | |||
|
265 | ||||
|
266 | For example, videos hosted externally on YouTube are easy to load (and writing a similar wrapper for other | |||
|
267 | hosted content is trivial): | |||
|
268 | ||||
|
269 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">YouTubeVideo</span> | |||
|
270 | <span class="c"># a talk about IPython at Sage Days at U. Washington, Seattle.</span> | |||
|
271 | <span class="c"># Video credit: William Stein.</span> | |||
|
272 | <span class="n">YouTubeVideo</span><span class="p">(</span><span class="s">'1j_HxD4iLn8'</span><span class="p">)</span> | |||
|
273 | </pre></div> | |||
|
274 | ||||
|
275 | ||||
|
276 | <pre> | |||
|
277 | <IPython.lib.display.YouTubeVideo at 0x10fba2190> | |||
|
278 | </pre> | |||
|
279 | ||||
|
280 | ||||
|
281 | Using the nascent video capabilities of modern browsers, you may also be able to display local | |||
|
282 | videos. At the moment this doesn't work very well in all browsers, so it may or may not work for you; | |||
|
283 | we will continue testing this and looking for ways to make it more robust. | |||
|
284 | ||||
|
285 | The following cell loads a local file called `animation.m4v`, encodes the raw video as base64 for http | |||
|
286 | transport, and uses the HTML5 video tag to load it. On Chrome 15 it works correctly, displaying a control | |||
|
287 | bar at the bottom with a play/pause button and a location slider. | |||
|
288 | ||||
|
289 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">HTML</span> | |||
|
290 | <span class="n">video</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"animation.m4v"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> | |||
|
291 | <span class="n">video_encoded</span> <span class="o">=</span> <span class="n">video</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">"base64"</span><span class="p">)</span> | |||
|
292 | <span class="n">video_tag</span> <span class="o">=</span> <span class="s">'<video controls alt="test" src="data:video/x-m4v;base64,{0}">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">video_encoded</span><span class="p">)</span> | |||
|
293 | <span class="n">HTML</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">video_tag</span><span class="p">)</span> | |||
|
294 | </pre></div> | |||
|
295 | ||||
|
296 | ||||
|
297 | <pre> | |||
|
298 | <IPython.core.display.HTML at 0x10fba28d0> | |||
|
299 | </pre> | |||
|
300 | ||||
|
301 | ||||
|
302 | ## Local Files | |||
|
303 | ||||
|
304 | The above examples embed images and video from the notebook filesystem in the output | |||
|
305 | areas of code cells. It is also possible to request these files directly in markdown cells | |||
|
306 | if they reside in the notebook directory via relative urls prefixed with `files/`: | |||
|
307 | ||||
|
308 | files/[subdirectory/]<filename> | |||
|
309 | ||||
|
310 | ||||
|
311 | For example, in the example notebook folder, we have the Python logo, addressed as: | |||
|
312 | ||||
|
313 | <img src="files/python-logo.svg" /> | |||
|
314 | ||||
|
315 | <img src="python-logo.svg" /> | |||
|
316 | ||||
|
317 | and a video with the HTML5 video tag: | |||
|
318 | ||||
|
319 | <video controls src="files/animation.m4v" /> | |||
|
320 | ||||
|
321 | <video controls src="animation.m4v" /> | |||
|
322 | ||||
|
323 | These do not embed the data into the notebook file, | |||
|
324 | and require that the files exist when you are viewing the notebook. | |||
|
325 | ||||
|
326 | ### Security of local files | |||
|
327 | ||||
|
328 | Note that this means that the IPython notebook server also acts as a generic file server | |||
|
329 | for files inside the same tree as your notebooks. Access is not granted outside the | |||
|
330 | notebook folder so you have strict control over what files are visible, but for this | |||
|
331 | reason it is highly recommended that you do not run the notebook server with a notebook | |||
|
332 | directory at a high level in your filesystem (e.g. your home directory). | |||
|
333 | ||||
|
334 | When you run the notebook in a password-protected manner, local file access is restricted | |||
|
335 | to authenticated users unless read-only views are active. | |||
|
336 | ||||
|
337 | ## Linking to files and directories for viewing in the browser | |||
|
338 | ||||
|
339 | It is also possible to link directly to files or directories so they can be opened in the browser. This is especially convenient if you're interacting with a tool within IPython that generates HTML pages, and you'd like to easily be able to open those in a new browser window. Alternatively, if your IPython notebook server is on a remote system, creating links provides an easy way to download any files that get generated. | |||
|
340 | ||||
|
341 | As we saw above, there are a bunch of `.ipynb` files in our current directory. | |||
|
342 | ||||
|
343 | <div class="highlight"><pre><span class="n">ls</span> | |||
|
344 | </pre></div> | |||
|
345 | ||||
|
346 | ||||
|
347 | 00_notebook_tour.ipynb formatting.ipynb | |||
|
348 | 01_notebook_introduction.ipynb octavemagic_extension.ipynb | |||
|
349 | Animations_and_Progress.ipynb publish_data.ipynb | |||
|
350 | Capturing Output.ipynb python-logo.svg | |||
|
351 | Script Magics.ipynb rmagic_extension.ipynb | |||
|
352 | animation.m4v sympy.ipynb | |||
|
353 | cython_extension.ipynb sympy_quantum_computing.ipynb | |||
|
354 | display_protocol.ipynb trapezoid_rule.ipynb | |||
|
355 | ||||
|
356 | ||||
|
357 | If we want to create a link to one of them, we can call use the `FileLink` object. | |||
|
358 | ||||
|
359 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">FileLink</span> | |||
|
360 | <span class="n">FileLink</span><span class="p">(</span><span class="s">'00_notebook_tour.ipynb'</span><span class="p">)</span> | |||
|
361 | </pre></div> | |||
|
362 | ||||
|
363 | ||||
|
364 | <pre> | |||
|
365 | <IPython.lib.display.FileLink at 0x10f7ea3d0> | |||
|
366 | </pre> | |||
|
367 | ||||
|
368 | ||||
|
369 | Alternatively, if we want to link to all of them, we can use the `FileLinks` object, passing `'.'` to indicate that we want links generated for the current working directory. Note that if there were other directories under the current directory, `FileLinks` would work in a recursive manner creating links to files in all sub-directories as well. | |||
|
370 | ||||
|
371 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">FileLinks</span> | |||
|
372 | <span class="n">FileLinks</span><span class="p">(</span><span class="s">'.'</span><span class="p">)</span> | |||
|
373 | </pre></div> | |||
|
374 | ||||
|
375 | ||||
|
376 | <pre> | |||
|
377 | <IPython.lib.display.FileLinks at 0x10f7eaad0> | |||
|
378 | </pre> | |||
|
379 | ||||
|
380 | ||||
|
381 | ### External sites | |||
|
382 | ||||
|
383 | You can even embed an entire page from another site in an iframe; for example this is today's Wikipedia | |||
|
384 | page for mobile users: | |||
|
385 | ||||
|
386 | <div class="highlight"><pre><span class="n">HTML</span><span class="p">(</span><span class="s">'<iframe src=http://en.mobile.wikipedia.org/?useformat=mobile width=700 height=350></iframe>'</span><span class="p">)</span> | |||
|
387 | </pre></div> | |||
|
388 | ||||
|
389 | ||||
|
390 | <pre> | |||
|
391 | <IPython.core.display.HTML at 0x1094900d0> | |||
|
392 | </pre> | |||
|
393 | ||||
|
394 | ||||
|
395 | ### Mathematics | |||
|
396 | ||||
|
397 | And we also support the display of mathematical expressions typeset in LaTeX, which is rendered | |||
|
398 | in the browser thanks to the [MathJax library](http://mathjax.org). | |||
|
399 | ||||
|
400 | Note that this is *different* from the above examples. Above we were typing mathematical expressions | |||
|
401 | in Markdown cells (along with normal text) and letting the browser render them; now we are displaying | |||
|
402 | the output of a Python computation as a LaTeX expression wrapped by the `Math()` object so the browser | |||
|
403 | renders it. The `Math` object will add the needed LaTeX delimiters (`$$`) if they are not provided: | |||
|
404 | ||||
|
405 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">Math</span> | |||
|
406 | <span class="n">Math</span><span class="p">(</span><span class="s">r'F(k) = \int_{-\infty}^{\infty} f(x) e^{2\pi i k} dx'</span><span class="p">)</span> | |||
|
407 | </pre></div> | |||
|
408 | ||||
|
409 | ||||
|
410 | <pre> | |||
|
411 | <IPython.core.display.Math at 0x10fba26d0> | |||
|
412 | </pre> | |||
|
413 | ||||
|
414 | ||||
|
415 | With the `Latex` class, you have to include the delimiters yourself. This allows you to use other LaTeX modes such as `eqnarray`: | |||
|
416 | ||||
|
417 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">Latex</span> | |||
|
418 | <span class="n">Latex</span><span class="p">(</span><span class="s">r"""\begin{eqnarray}</span> | |||
|
419 | <span class="s">\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\</span> | |||
|
420 | <span class="s">\nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\</span> | |||
|
421 | <span class="s">\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\</span> | |||
|
422 | <span class="s">\nabla \cdot \vec{\mathbf{B}} & = 0 </span> | |||
|
423 | <span class="s">\end{eqnarray}"""</span><span class="p">)</span> | |||
|
424 | </pre></div> | |||
|
425 | ||||
|
426 | ||||
|
427 | <pre> | |||
|
428 | <IPython.core.display.Latex at 0x10fba2c10> | |||
|
429 | </pre> | |||
|
430 | ||||
|
431 | ||||
|
432 | Or you can enter latex directly with the `%%latex` cell magic: | |||
|
433 | ||||
|
434 | <div class="highlight"><pre><span class="o">%%</span><span class="k">latex</span> | |||
|
435 | \<span class="n">begin</span><span class="p">{</span><span class="n">aligned</span><span class="p">}</span> | |||
|
436 | \<span class="n">nabla</span> \<span class="n">times</span> \<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">B</span><span class="p">}}</span> <span class="o">-</span>\<span class="p">,</span> \<span class="n">frac1c</span>\<span class="p">,</span> \<span class="n">frac</span><span class="p">{</span>\<span class="n">partial</span>\<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">E</span><span class="p">}}}{</span>\<span class="n">partial</span> <span class="n">t</span><span class="p">}</span> <span class="o">&</span> <span class="o">=</span> \<span class="n">frac</span><span class="p">{</span><span class="mi">4</span>\<span class="n">pi</span><span class="p">}{</span><span class="n">c</span><span class="p">}</span>\<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">j</span><span class="p">}}</span> \\ | |||
|
437 | \<span class="n">nabla</span> \<span class="n">cdot</span> \<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">E</span><span class="p">}}</span> <span class="o">&</span> <span class="o">=</span> <span class="mi">4</span> \<span class="n">pi</span> \<span class="n">rho</span> \\ | |||
|
438 | \<span class="n">nabla</span> \<span class="n">times</span> \<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">E</span><span class="p">}}</span>\<span class="p">,</span> <span class="o">+</span>\<span class="p">,</span> \<span class="n">frac1c</span>\<span class="p">,</span> \<span class="n">frac</span><span class="p">{</span>\<span class="n">partial</span>\<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">B</span><span class="p">}}}{</span>\<span class="n">partial</span> <span class="n">t</span><span class="p">}</span> <span class="o">&</span> <span class="o">=</span> \<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="mi">0</span><span class="p">}}</span> \\ | |||
|
439 | \<span class="n">nabla</span> \<span class="n">cdot</span> \<span class="n">vec</span><span class="p">{</span>\<span class="n">mathbf</span><span class="p">{</span><span class="n">B</span><span class="p">}}</span> <span class="o">&</span> <span class="o">=</span> <span class="mi">0</span> | |||
|
440 | \<span class="n">end</span><span class="p">{</span><span class="n">aligned</span><span class="p">}</span> | |||
|
441 | </pre></div> | |||
|
442 | ||||
|
443 | ||||
|
444 | <IPython.core.display.Latex at 0x10a617c90> | |||
|
445 | ||||
|
446 | There is also a `%%javascript` cell magic for running javascript directly, | |||
|
447 | and `%%svg` for manually entering SVG content. | |||
|
448 | ||||
|
449 | # Loading external codes | |||
|
450 | * Drag and drop a ``.py`` in the dashboard | |||
|
451 | * Use ``%load`` with any local or remote url: [the Matplotlib Gallery!](http://matplotlib.sourceforge.net/gallery.html) | |||
|
452 | ||||
|
453 | In this notebook we've kept the output saved so you can see the result, but you should run the next | |||
|
454 | cell yourself (with an active internet connection). | |||
|
455 | ||||
|
456 | Let's make sure we have pylab again, in case we have restarted the kernel due to the crash demo above | |||
|
457 | ||||
|
458 | <div class="highlight"><pre><span class="o">%</span><span class="k">pylab</span> <span class="n">inline</span> | |||
|
459 | </pre></div> | |||
|
460 | ||||
|
461 | ||||
|
462 | ||||
|
463 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
464 | For more information, type 'help(pylab)'. | |||
|
465 | ||||
|
466 | ||||
|
467 | <div class="highlight"><pre><span class="o">%</span><span class="k">load</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">matplotlib</span><span class="o">.</span><span class="n">sourceforge</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">mpl_examples</span><span class="o">/</span><span class="n">pylab_examples</span><span class="o">/</span><span class="n">integral_demo</span><span class="o">.</span><span class="n">py</span> | |||
|
468 | </pre></div> | |||
|
469 | ||||
|
470 | ||||
|
471 | ||||
|
472 | <div class="highlight"><pre><span class="c">#!/usr/bin/env python</span> | |||
|
473 | ||||
|
474 | <span class="c"># implement the example graphs/integral from pyx</span> | |||
|
475 | <span class="kn">from</span> <span class="nn">pylab</span> <span class="kn">import</span> <span class="o">*</span> | |||
|
476 | <span class="kn">from</span> <span class="nn">matplotlib.patches</span> <span class="kn">import</span> <span class="n">Polygon</span> | |||
|
477 | ||||
|
478 | <span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> | |||
|
479 | <span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">3</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">5</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">7</span><span class="p">)</span><span class="o">+</span><span class="mi">85</span> | |||
|
480 | ||||
|
481 | <span class="n">ax</span> <span class="o">=</span> <span class="n">subplot</span><span class="p">(</span><span class="mi">111</span><span class="p">)</span> | |||
|
482 | ||||
|
483 | <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">9</span> <span class="c"># integral area</span> | |||
|
484 | <span class="n">x</span> <span class="o">=</span> <span class="n">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mf">0.01</span><span class="p">)</span> | |||
|
485 | <span class="n">y</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> | |||
|
486 | <span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">linewidth</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> | |||
|
487 | ||||
|
488 | <span class="c"># make the shaded region</span> | |||
|
489 | <span class="n">ix</span> <span class="o">=</span> <span class="n">arange</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="mf">0.01</span><span class="p">)</span> | |||
|
490 | <span class="n">iy</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">ix</span><span class="p">)</span> | |||
|
491 | <span class="n">verts</span> <span class="o">=</span> <span class="p">[(</span><span class="n">a</span><span class="p">,</span><span class="mi">0</span><span class="p">)]</span> <span class="o">+</span> <span class="nb">zip</span><span class="p">(</span><span class="n">ix</span><span class="p">,</span><span class="n">iy</span><span class="p">)</span> <span class="o">+</span> <span class="p">[(</span><span class="n">b</span><span class="p">,</span><span class="mi">0</span><span class="p">)]</span> | |||
|
492 | <span class="n">poly</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span><span class="n">verts</span><span class="p">,</span> <span class="n">facecolor</span><span class="o">=</span><span class="s">'0.8'</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'k'</span><span class="p">)</span> | |||
|
493 | <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">poly</span><span class="p">)</span> | |||
|
494 | ||||
|
495 | <span class="n">text</span><span class="p">(</span><span class="mf">0.5</span> <span class="o">*</span> <span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">),</span> <span class="mi">30</span><span class="p">,</span> | |||
|
496 | <span class="s">r"$\int_a^b f(x)\mathrm{d}x$"</span><span class="p">,</span> <span class="n">horizontalalignment</span><span class="o">=</span><span class="s">'center'</span><span class="p">,</span> | |||
|
497 | <span class="n">fontsize</span><span class="o">=</span><span class="mi">20</span><span class="p">)</span> | |||
|
498 | ||||
|
499 | <span class="n">axis</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">180</span><span class="p">])</span> | |||
|
500 | <span class="n">figtext</span><span class="p">(</span><span class="mf">0.9</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">,</span> <span class="s">'x'</span><span class="p">)</span> | |||
|
501 | <span class="n">figtext</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.9</span><span class="p">,</span> <span class="s">'y'</span><span class="p">)</span> | |||
|
502 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">((</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">))</span> | |||
|
503 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xticklabels</span><span class="p">((</span><span class="s">'a'</span><span class="p">,</span><span class="s">'b'</span><span class="p">))</span> | |||
|
504 | <span class="n">ax</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">([])</span> | |||
|
505 | <span class="n">show</span><span class="p">()</span> | |||
|
506 | </pre></div> | |||
|
507 | ||||
|
508 | ||||
|
509 | ||||
|
510 | ![](tests/ipynbref/00_notebook_tour_orig_files/00_notebook_tour_orig_fig_01.png) | |||
|
511 |
This diff has been collapsed as it changes many lines, (828 lines changed) Show them Hide them | |||||
@@ -0,0 +1,828 b'' | |||||
|
1 | %% This file was auto-generated by IPython. | |||
|
2 | %% Conversion from the original notebook file: | |||
|
3 | %% tests/ipynbref/00_notebook_tour.orig.ipynb | |||
|
4 | %% | |||
|
5 | \documentclass[11pt,english]{article} | |||
|
6 | ||||
|
7 | %% This is the automatic preamble used by IPython. Note that it does *not* | |||
|
8 | %% include a documentclass declaration, that is added at runtime to the overall | |||
|
9 | %% document. | |||
|
10 | ||||
|
11 | \usepackage{amsmath} | |||
|
12 | \usepackage{amssymb} | |||
|
13 | \usepackage{graphicx} | |||
|
14 | \usepackage{ucs} | |||
|
15 | \usepackage[utf8x]{inputenc} | |||
|
16 | ||||
|
17 | % needed for markdown enumerations to work | |||
|
18 | \usepackage{enumerate} | |||
|
19 | ||||
|
20 | % Slightly bigger margins than the latex defaults | |||
|
21 | \usepackage{geometry} | |||
|
22 | \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm} | |||
|
23 | ||||
|
24 | % Define a few colors for use in code, links and cell shading | |||
|
25 | \usepackage{color} | |||
|
26 | \definecolor{orange}{cmyk}{0,0.4,0.8,0.2} | |||
|
27 | \definecolor{darkorange}{rgb}{.71,0.21,0.01} | |||
|
28 | \definecolor{darkgreen}{rgb}{.12,.54,.11} | |||
|
29 | \definecolor{myteal}{rgb}{.26, .44, .56} | |||
|
30 | \definecolor{gray}{gray}{0.45} | |||
|
31 | \definecolor{lightgray}{gray}{.95} | |||
|
32 | \definecolor{mediumgray}{gray}{.8} | |||
|
33 | \definecolor{inputbackground}{rgb}{.95, .95, .85} | |||
|
34 | \definecolor{outputbackground}{rgb}{.95, .95, .95} | |||
|
35 | \definecolor{traceback}{rgb}{1, .95, .95} | |||
|
36 | ||||
|
37 | % Framed environments for code cells (inputs, outputs, errors, ...). The | |||
|
38 | % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't | |||
|
39 | % randomly change them unless you're sure of the effect it will have. | |||
|
40 | \usepackage{framed} | |||
|
41 | ||||
|
42 | % remove extraneous vertical space in boxes | |||
|
43 | \setlength\fboxsep{0pt} | |||
|
44 | ||||
|
45 | % codecell is the whole input+output set of blocks that a Code cell can | |||
|
46 | % generate. | |||
|
47 | ||||
|
48 | % TODO: unfortunately, it seems that using a framed codecell environment breaks | |||
|
49 | % the ability of the frames inside of it to be broken across pages. This | |||
|
50 | % causes at least the problem of having lots of empty space at the bottom of | |||
|
51 | % pages as new frames are moved to the next page, and if a single frame is too | |||
|
52 | % long to fit on a page, will completely stop latex from compiling the | |||
|
53 | % document. So unless we figure out a solution to this, we'll have to instead | |||
|
54 | % leave the codecell env. as empty. I'm keeping the original codecell | |||
|
55 | % definition here (a thin vertical bar) for reference, in case we find a | |||
|
56 | % solution to the page break issue. | |||
|
57 | ||||
|
58 | %% \newenvironment{codecell}{% | |||
|
59 | %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}% | |||
|
60 | %% \MakeFramed{\vspace{-0.5em}}} | |||
|
61 | %% {\unskip\endMakeFramed} | |||
|
62 | ||||
|
63 | % For now, make this a no-op... | |||
|
64 | \newenvironment{codecell}{} | |||
|
65 | ||||
|
66 | \newenvironment{codeinput}{% | |||
|
67 | \def\FrameCommand{\colorbox{inputbackground}}% | |||
|
68 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
69 | {\unskip\endMakeFramed} | |||
|
70 | ||||
|
71 | \newenvironment{codeoutput}{% | |||
|
72 | \def\FrameCommand{\colorbox{outputbackground}}% | |||
|
73 | \vspace{-1.4em} | |||
|
74 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
75 | {\unskip\medskip\endMakeFramed} | |||
|
76 | ||||
|
77 | \newenvironment{traceback}{% | |||
|
78 | \def\FrameCommand{\colorbox{traceback}}% | |||
|
79 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
80 | {\endMakeFramed} | |||
|
81 | ||||
|
82 | % Use and configure listings package for nicely formatted code | |||
|
83 | \usepackage{listingsutf8} | |||
|
84 | \lstset{ | |||
|
85 | language=python, | |||
|
86 | inputencoding=utf8x, | |||
|
87 | extendedchars=\true, | |||
|
88 | aboveskip=\smallskipamount, | |||
|
89 | belowskip=\smallskipamount, | |||
|
90 | xleftmargin=2mm, | |||
|
91 | breaklines=true, | |||
|
92 | basicstyle=\small \ttfamily, | |||
|
93 | showstringspaces=false, | |||
|
94 | keywordstyle=\color{blue}\bfseries, | |||
|
95 | commentstyle=\color{myteal}, | |||
|
96 | stringstyle=\color{darkgreen}, | |||
|
97 | identifierstyle=\color{darkorange}, | |||
|
98 | columns=fullflexible, % tighter character kerning, like verb | |||
|
99 | } | |||
|
100 | ||||
|
101 | % The hyperref package gives us a pdf with properly built | |||
|
102 | % internal navigation ('pdf bookmarks' for the table of contents, | |||
|
103 | % internal cross-reference links, web links for URLs, etc.) | |||
|
104 | \usepackage{hyperref} | |||
|
105 | \hypersetup{ | |||
|
106 | breaklinks=true, % so long urls are correctly broken across lines | |||
|
107 | colorlinks=true, | |||
|
108 | urlcolor=blue, | |||
|
109 | linkcolor=darkorange, | |||
|
110 | citecolor=darkgreen, | |||
|
111 | } | |||
|
112 | ||||
|
113 | % hardcode size of all verbatim environments to be a bit smaller | |||
|
114 | \makeatletter | |||
|
115 | \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt | |||
|
116 | \makeatother | |||
|
117 | ||||
|
118 | % Prevent overflowing lines due to urls and other hard-to-break entities. | |||
|
119 | \sloppy | |||
|
120 | ||||
|
121 | \begin{document} | |||
|
122 | ||||
|
123 | \section{A brief tour of the IPython notebook} | |||
|
124 | ||||
|
125 | This document will give you a brief tour of the capabilities of the | |||
|
126 | IPython notebook.\\You can view its contents by scrolling around, or | |||
|
127 | execute each cell by typing \texttt{Shift-Enter}. After you conclude | |||
|
128 | this brief high-level tour, you should read the accompanying notebook | |||
|
129 | titled \texttt{01\_notebook\_introduction}, which takes a more | |||
|
130 | step-by-step approach to the features of the system. | |||
|
131 | ||||
|
132 | The rest of the notebooks in this directory illustrate various other | |||
|
133 | aspects and capabilities of the IPython notebook; some of them may | |||
|
134 | require additional libraries to be executed. | |||
|
135 | ||||
|
136 | \textbf{NOTE:} This notebook \emph{must} be run from its own directory, | |||
|
137 | so you must \texttt{cd} to this directory and then start the notebook, | |||
|
138 | but do \emph{not} use the \texttt{-{}-notebook-dir} option to run it | |||
|
139 | from another location. | |||
|
140 | ||||
|
141 | The first thing you need to know is that you are still controlling the | |||
|
142 | same old IPython you're used to, so things like shell aliases and magic | |||
|
143 | commands still work: | |||
|
144 | ||||
|
145 | \begin{codecell} | |||
|
146 | \begin{codeinput} | |||
|
147 | \begin{lstlisting} | |||
|
148 | pwd | |||
|
149 | \end{lstlisting} | |||
|
150 | \end{codeinput} | |||
|
151 | \begin{codeoutput} | |||
|
152 | \begin{verbatim} | |||
|
153 | u'/Users/minrk/dev/ip/mine/docs/examples/notebooks' | |||
|
154 | \end{verbatim} | |||
|
155 | \end{codeoutput} | |||
|
156 | \end{codecell} | |||
|
157 | \begin{codecell} | |||
|
158 | \begin{codeinput} | |||
|
159 | \begin{lstlisting} | |||
|
160 | ls | |||
|
161 | \end{lstlisting} | |||
|
162 | \end{codeinput} | |||
|
163 | \begin{codeoutput} | |||
|
164 | \begin{verbatim} | |||
|
165 | 00_notebook_tour.ipynb callbacks.ipynb python-logo.svg | |||
|
166 | 01_notebook_introduction.ipynb cython_extension.ipynb rmagic_extension.ipynb | |||
|
167 | Animations_and_Progress.ipynb display_protocol.ipynb sympy.ipynb | |||
|
168 | Capturing Output.ipynb formatting.ipynb sympy_quantum_computing.ipynb | |||
|
169 | Script Magics.ipynb octavemagic_extension.ipynb trapezoid_rule.ipynb | |||
|
170 | animation.m4v progbar.ipynb | |||
|
171 | \end{verbatim} | |||
|
172 | \end{codeoutput} | |||
|
173 | \end{codecell} | |||
|
174 | \begin{codecell} | |||
|
175 | \begin{codeinput} | |||
|
176 | \begin{lstlisting} | |||
|
177 | message = 'The IPython notebook is great!' | |||
|
178 | # note: the echo command does not run on Windows, it's a unix command. | |||
|
179 | !echo $message | |||
|
180 | \end{lstlisting} | |||
|
181 | \end{codeinput} | |||
|
182 | \begin{codeoutput} | |||
|
183 | \begin{verbatim} | |||
|
184 | The IPython notebook is great! | |||
|
185 | \end{verbatim} | |||
|
186 | \end{codeoutput} | |||
|
187 | \end{codecell} | |||
|
188 | \subsection{Plots with matplotlib} | |||
|
189 | IPython adds an `inline' matplotlib backend, which embeds any matplotlib | |||
|
190 | figures into the notebook. | |||
|
191 | ||||
|
192 | \begin{codecell} | |||
|
193 | \begin{codeinput} | |||
|
194 | \begin{lstlisting} | |||
|
195 | %pylab inline | |||
|
196 | \end{lstlisting} | |||
|
197 | \end{codeinput} | |||
|
198 | \begin{codeoutput} | |||
|
199 | \begin{verbatim} | |||
|
200 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
201 | For more information, type 'help(pylab)'. | |||
|
202 | \end{verbatim} | |||
|
203 | \end{codeoutput} | |||
|
204 | \end{codecell} | |||
|
205 | \begin{codecell} | |||
|
206 | \begin{codeinput} | |||
|
207 | \begin{lstlisting} | |||
|
208 | x = linspace(0, 3*pi, 500) | |||
|
209 | plot(x, sin(x**2)) | |||
|
210 | title('A simple chirp'); | |||
|
211 | \end{lstlisting} | |||
|
212 | \end{codeinput} | |||
|
213 | \begin{codeoutput} | |||
|
214 | \begin{center} | |||
|
215 | \includegraphics[width=0.7\textwidth]{00_notebook_tour_orig_files/00_notebook_tour_orig_fig_00.png} | |||
|
216 | \par | |||
|
217 | \end{center} | |||
|
218 | \end{codeoutput} | |||
|
219 | \end{codecell} | |||
|
220 | You can paste blocks of input with prompt markers, such as those from | |||
|
221 | \href{http://docs.python.org/tutorial/interpreter.html\#interactive-mode}{the | |||
|
222 | official Python tutorial} | |||
|
223 | ||||
|
224 | \begin{codecell} | |||
|
225 | \begin{codeinput} | |||
|
226 | \begin{lstlisting} | |||
|
227 | >>> the_world_is_flat = 1 | |||
|
228 | >>> if the_world_is_flat: | |||
|
229 | ... print "Be careful not to fall off!" | |||
|
230 | \end{lstlisting} | |||
|
231 | \end{codeinput} | |||
|
232 | \begin{codeoutput} | |||
|
233 | \begin{verbatim} | |||
|
234 | Be careful not to fall off! | |||
|
235 | \end{verbatim} | |||
|
236 | \end{codeoutput} | |||
|
237 | \end{codecell} | |||
|
238 | Errors are shown in informative ways: | |||
|
239 | ||||
|
240 | \begin{codecell} | |||
|
241 | \begin{codeinput} | |||
|
242 | \begin{lstlisting} | |||
|
243 | %run non_existent_file | |||
|
244 | \end{lstlisting} | |||
|
245 | \end{codeinput} | |||
|
246 | \begin{codeoutput} | |||
|
247 | \begin{verbatim} | |||
|
248 | ERROR: File `u'non_existent_file.py'` not found. | |||
|
249 | \end{verbatim} | |||
|
250 | \end{codeoutput} | |||
|
251 | \end{codecell} | |||
|
252 | \begin{codecell} | |||
|
253 | \begin{codeinput} | |||
|
254 | \begin{lstlisting} | |||
|
255 | x = 1 | |||
|
256 | y = 4 | |||
|
257 | z = y/(1-x) | |||
|
258 | \end{lstlisting} | |||
|
259 | \end{codeinput} | |||
|
260 | \begin{codeoutput} | |||
|
261 | \begin{traceback} | |||
|
262 | \begin{verbatim} | |||
|
263 | --------------------------------------------------------------------------- | |||
|
264 | ZeroDivisionError Traceback (most recent call last) | |||
|
265 | <ipython-input-8-dc39888fd1d2> in <module>() | |||
|
266 | 1 x = 1 | |||
|
267 | 2 y = 4 | |||
|
268 | ----> 3 z = y/(1-x) | |||
|
269 | ||||
|
270 | ZeroDivisionError: integer division or modulo by zero | |||
|
271 | \end{verbatim} | |||
|
272 | \end{traceback} | |||
|
273 | \end{codeoutput} | |||
|
274 | \end{codecell} | |||
|
275 | When IPython needs to display additional information (such as providing | |||
|
276 | details on an object via \texttt{x?} it will automatically invoke a | |||
|
277 | pager at the bottom of the screen: | |||
|
278 | ||||
|
279 | \begin{codecell} | |||
|
280 | \begin{codeinput} | |||
|
281 | \begin{lstlisting} | |||
|
282 | magic | |||
|
283 | \end{lstlisting} | |||
|
284 | \end{codeinput} | |||
|
285 | \end{codecell} | |||
|
286 | \subsection{Non-blocking output of kernel} | |||
|
287 | ||||
|
288 | If you execute the next cell, you will see the output arriving as it is | |||
|
289 | generated, not all at the end. | |||
|
290 | ||||
|
291 | \begin{codecell} | |||
|
292 | \begin{codeinput} | |||
|
293 | \begin{lstlisting} | |||
|
294 | import time, sys | |||
|
295 | for i in range(8): | |||
|
296 | print i, | |||
|
297 | time.sleep(0.5) | |||
|
298 | \end{lstlisting} | |||
|
299 | \end{codeinput} | |||
|
300 | \begin{codeoutput} | |||
|
301 | \begin{verbatim} | |||
|
302 | 0 | |||
|
303 | \end{verbatim} | |||
|
304 | \begin{verbatim} | |||
|
305 | 1 | |||
|
306 | \end{verbatim} | |||
|
307 | \begin{verbatim} | |||
|
308 | 2 | |||
|
309 | \end{verbatim} | |||
|
310 | \begin{verbatim} | |||
|
311 | 3 | |||
|
312 | \end{verbatim} | |||
|
313 | \begin{verbatim} | |||
|
314 | 4 | |||
|
315 | \end{verbatim} | |||
|
316 | \begin{verbatim} | |||
|
317 | 5 | |||
|
318 | \end{verbatim} | |||
|
319 | \begin{verbatim} | |||
|
320 | 6 | |||
|
321 | \end{verbatim} | |||
|
322 | \begin{verbatim} | |||
|
323 | 7 | |||
|
324 | \end{verbatim} | |||
|
325 | \end{codeoutput} | |||
|
326 | \end{codecell} | |||
|
327 | \subsection{Clean crash and restart} | |||
|
328 | ||||
|
329 | We call the low-level system libc.time routine with the wrong argument | |||
|
330 | via ctypes to segfault the Python interpreter: | |||
|
331 | ||||
|
332 | \begin{codecell} | |||
|
333 | \begin{codeinput} | |||
|
334 | \begin{lstlisting} | |||
|
335 | import sys | |||
|
336 | from ctypes import CDLL | |||
|
337 | # This will crash a Linux or Mac system; equivalent calls can be made on Windows | |||
|
338 | dll = 'dylib' if sys.platform == 'darwin' else '.so.6' | |||
|
339 | libc = CDLL("libc.%s" % dll) | |||
|
340 | libc.time(-1) # BOOM!! | |||
|
341 | \end{lstlisting} | |||
|
342 | \end{codeinput} | |||
|
343 | \end{codecell} | |||
|
344 | \subsection{Markdown cells can contain formatted text and code} | |||
|
345 | ||||
|
346 | You can \emph{italicize}, \textbf{boldface} | |||
|
347 | ||||
|
348 | \begin{itemize} | |||
|
349 | \item | |||
|
350 | build | |||
|
351 | \item | |||
|
352 | lists | |||
|
353 | \end{itemize} | |||
|
354 | and embed code meant for illustration instead of execution in Python: | |||
|
355 | ||||
|
356 | \begin{verbatim} | |||
|
357 | def f(x): | |||
|
358 | """a docstring""" | |||
|
359 | return x**2 | |||
|
360 | \end{verbatim} | |||
|
361 | or other languages: | |||
|
362 | ||||
|
363 | \begin{verbatim} | |||
|
364 | if (i=0; i<n; i++) { | |||
|
365 | printf("hello %d\n", i); | |||
|
366 | x += 4; | |||
|
367 | } | |||
|
368 | \end{verbatim} | |||
|
369 | ||||
|
370 | ||||
|
371 | Courtesy of MathJax, you can include mathematical expressions both | |||
|
372 | inline: $e^{i\pi} + 1 = 0$ and displayed: | |||
|
373 | ||||
|
374 | \[e^x=\sum_{i=0}^\infty \frac{1}{i!}x^i\] | |||
|
375 | ||||
|
376 | \subsection{Rich displays: include anyting a browser can show} | |||
|
377 | ||||
|
378 | Note that we have an actual protocol for this, see the | |||
|
379 | \texttt{display\_protocol} notebook for further details. | |||
|
380 | ||||
|
381 | \subsubsection{Images} | |||
|
382 | ||||
|
383 | ||||
|
384 | \begin{codecell} | |||
|
385 | \begin{codeinput} | |||
|
386 | \begin{lstlisting} | |||
|
387 | from IPython.display import Image | |||
|
388 | Image(filename='../../source/_static/logo.png') | |||
|
389 | \end{lstlisting} | |||
|
390 | \end{codeinput} | |||
|
391 | \begin{codeoutput} | |||
|
392 | \begin{verbatim} | |||
|
393 | <IPython.core.display.Image at 0x10faeafd0> | |||
|
394 | \end{verbatim} | |||
|
395 | \end{codeoutput} | |||
|
396 | \end{codecell} | |||
|
397 | An image can also be displayed from raw data or a url | |||
|
398 | ||||
|
399 | \begin{codecell} | |||
|
400 | \begin{codeinput} | |||
|
401 | \begin{lstlisting} | |||
|
402 | Image(url='http://python.org/images/python-logo.gif') | |||
|
403 | \end{lstlisting} | |||
|
404 | \end{codeinput} | |||
|
405 | \begin{codeoutput} | |||
|
406 | \begin{verbatim} | |||
|
407 | <IPython.core.display.Image at 0x1060e7410> | |||
|
408 | \end{verbatim} | |||
|
409 | \end{codeoutput} | |||
|
410 | \end{codecell} | |||
|
411 | SVG images are also supported out of the box (since modern browsers do a | |||
|
412 | good job of rendering them): | |||
|
413 | ||||
|
414 | \begin{codecell} | |||
|
415 | \begin{codeinput} | |||
|
416 | \begin{lstlisting} | |||
|
417 | from IPython.display import SVG | |||
|
418 | SVG(filename='python-logo.svg') | |||
|
419 | \end{lstlisting} | |||
|
420 | \end{codeinput} | |||
|
421 | \begin{codeoutput} | |||
|
422 | \begin{verbatim} | |||
|
423 | <IPython.core.display.SVG at 0x10fb998d0> | |||
|
424 | \end{verbatim} | |||
|
425 | \end{codeoutput} | |||
|
426 | \end{codecell} | |||
|
427 | \paragraph{Embedded vs Non-embedded Images} | |||
|
428 | ||||
|
429 | ||||
|
430 | As of IPython 0.13, images are embedded by default for compatibility | |||
|
431 | with QtConsole, and the ability to still be displayed offline. | |||
|
432 | ||||
|
433 | Let's look at the differences: | |||
|
434 | ||||
|
435 | \begin{codecell} | |||
|
436 | \begin{codeinput} | |||
|
437 | \begin{lstlisting} | |||
|
438 | # by default Image data are embedded | |||
|
439 | Embed = Image( 'http://scienceview.berkeley.edu/view/images/newview.jpg') | |||
|
440 | ||||
|
441 | # if kwarg `url` is given, the embedding is assumed to be false | |||
|
442 | SoftLinked = Image(url='http://scienceview.berkeley.edu/view/images/newview.jpg') | |||
|
443 | ||||
|
444 | # In each case, embed can be specified explicitly with the `embed` kwarg | |||
|
445 | # ForceEmbed = Image(url='http://scienceview.berkeley.edu/view/images/newview.jpg', embed=True) | |||
|
446 | \end{lstlisting} | |||
|
447 | \end{codeinput} | |||
|
448 | \end{codecell} | |||
|
449 | Today's image from a webcam at Berkeley, (at the time I created this | |||
|
450 | notebook). This should also work in the Qtconsole. Drawback is that the | |||
|
451 | saved notebook will be larger, but the image will still be present | |||
|
452 | offline. | |||
|
453 | ||||
|
454 | \begin{codecell} | |||
|
455 | \begin{codeinput} | |||
|
456 | \begin{lstlisting} | |||
|
457 | Embed | |||
|
458 | \end{lstlisting} | |||
|
459 | \end{codeinput} | |||
|
460 | \begin{codeoutput} | |||
|
461 | \begin{verbatim} | |||
|
462 | <IPython.core.display.Image at 0x10fb99b50> | |||
|
463 | \end{verbatim} | |||
|
464 | \end{codeoutput} | |||
|
465 | \end{codecell} | |||
|
466 | Today's image from same webcam at Berkeley, (refreshed every minutes, if | |||
|
467 | you reload the notebook), visible only with an active internet | |||
|
468 | connexion, that should be different from the previous one. This will not | |||
|
469 | work on Qtconsole. Notebook saved with this kind of image will be | |||
|
470 | lighter and always reflect the current version of the source, but the | |||
|
471 | image won't display offline. | |||
|
472 | ||||
|
473 | \begin{codecell} | |||
|
474 | \begin{codeinput} | |||
|
475 | \begin{lstlisting} | |||
|
476 | SoftLinked | |||
|
477 | \end{lstlisting} | |||
|
478 | \end{codeinput} | |||
|
479 | \begin{codeoutput} | |||
|
480 | \begin{verbatim} | |||
|
481 | <IPython.core.display.Image at 0x10fb99b10> | |||
|
482 | \end{verbatim} | |||
|
483 | \end{codeoutput} | |||
|
484 | \end{codecell} | |||
|
485 | Of course, if you re-run the all notebook, the two images will be the | |||
|
486 | same again. | |||
|
487 | ||||
|
488 | \subsubsection{Video} | |||
|
489 | ||||
|
490 | ||||
|
491 | And more exotic objects can also be displayed, as long as their | |||
|
492 | representation supports the IPython display protocol. | |||
|
493 | ||||
|
494 | For example, videos hosted externally on YouTube are easy to load (and | |||
|
495 | writing a similar wrapper for other hosted content is trivial): | |||
|
496 | ||||
|
497 | \begin{codecell} | |||
|
498 | \begin{codeinput} | |||
|
499 | \begin{lstlisting} | |||
|
500 | from IPython.display import YouTubeVideo | |||
|
501 | # a talk about IPython at Sage Days at U. Washington, Seattle. | |||
|
502 | # Video credit: William Stein. | |||
|
503 | YouTubeVideo('1j_HxD4iLn8') | |||
|
504 | \end{lstlisting} | |||
|
505 | \end{codeinput} | |||
|
506 | \begin{codeoutput} | |||
|
507 | \begin{verbatim} | |||
|
508 | <IPython.lib.display.YouTubeVideo at 0x10fba2190> | |||
|
509 | \end{verbatim} | |||
|
510 | \end{codeoutput} | |||
|
511 | \end{codecell} | |||
|
512 | Using the nascent video capabilities of modern browsers, you may also be | |||
|
513 | able to display local videos. At the moment this doesn't work very well | |||
|
514 | in all browsers, so it may or may not work for you; we will continue | |||
|
515 | testing this and looking for ways to make it more robust. | |||
|
516 | ||||
|
517 | The following cell loads a local file called \texttt{animation.m4v}, | |||
|
518 | encodes the raw video as base64 for http transport, and uses the HTML5 | |||
|
519 | video tag to load it. On Chrome 15 it works correctly, displaying a | |||
|
520 | control bar at the bottom with a play/pause button and a location | |||
|
521 | slider. | |||
|
522 | ||||
|
523 | \begin{codecell} | |||
|
524 | \begin{codeinput} | |||
|
525 | \begin{lstlisting} | |||
|
526 | from IPython.display import HTML | |||
|
527 | video = open("animation.m4v", "rb").read() | |||
|
528 | video_encoded = video.encode("base64") | |||
|
529 | video_tag = '<video controls alt="test" src="data:video/x-m4v;base64,{0}">'.format(video_encoded) | |||
|
530 | HTML(data=video_tag) | |||
|
531 | \end{lstlisting} | |||
|
532 | \end{codeinput} | |||
|
533 | \begin{codeoutput} | |||
|
534 | \begin{verbatim} | |||
|
535 | <IPython.core.display.HTML at 0x10fba28d0> | |||
|
536 | \end{verbatim} | |||
|
537 | \end{codeoutput} | |||
|
538 | \end{codecell} | |||
|
539 | \subsection{Local Files} | |||
|
540 | ||||
|
541 | The above examples embed images and video from the notebook filesystem | |||
|
542 | in the output areas of code cells. It is also possible to request these | |||
|
543 | files directly in markdown cells if they reside in the notebook | |||
|
544 | directory via relative urls prefixed with \texttt{files/}: | |||
|
545 | ||||
|
546 | \begin{verbatim} | |||
|
547 | files/[subdirectory/]<filename> | |||
|
548 | \end{verbatim} | |||
|
549 | For example, in the example notebook folder, we have the Python logo, | |||
|
550 | addressed as: | |||
|
551 | ||||
|
552 | \begin{verbatim} | |||
|
553 | <img src="files/python-logo.svg" /> | |||
|
554 | \end{verbatim} | |||
|
555 | and a video with the HTML5 video tag: | |||
|
556 | ||||
|
557 | \begin{verbatim} | |||
|
558 | <video controls src="files/animation.m4v" /> | |||
|
559 | \end{verbatim} | |||
|
560 | These do not embed the data into the notebook file, and require that the | |||
|
561 | files exist when you are viewing the notebook. | |||
|
562 | ||||
|
563 | \subsubsection{Security of local files} | |||
|
564 | ||||
|
565 | Note that this means that the IPython notebook server also acts as a | |||
|
566 | generic file server for files inside the same tree as your notebooks. | |||
|
567 | Access is not granted outside the notebook folder so you have strict | |||
|
568 | control over what files are visible, but for this reason it is highly | |||
|
569 | recommended that you do not run the notebook server with a notebook | |||
|
570 | directory at a high level in your filesystem (e.g.~your home directory). | |||
|
571 | ||||
|
572 | When you run the notebook in a password-protected manner, local file | |||
|
573 | access is restricted to authenticated users unless read-only views are | |||
|
574 | active. | |||
|
575 | ||||
|
576 | \subsection{Linking to files and directories for viewing in the browser} | |||
|
577 | ||||
|
578 | It is also possible to link directly to files or directories so they can | |||
|
579 | be opened in the browser. This is especially convenient if you're | |||
|
580 | interacting with a tool within IPython that generates HTML pages, and | |||
|
581 | you'd like to easily be able to open those in a new browser window. | |||
|
582 | Alternatively, if your IPython notebook server is on a remote system, | |||
|
583 | creating links provides an easy way to download any files that get | |||
|
584 | generated. | |||
|
585 | ||||
|
586 | As we saw above, there are a bunch of \texttt{.ipynb} files in our | |||
|
587 | current directory. | |||
|
588 | ||||
|
589 | \begin{codecell} | |||
|
590 | \begin{codeinput} | |||
|
591 | \begin{lstlisting} | |||
|
592 | ls | |||
|
593 | \end{lstlisting} | |||
|
594 | \end{codeinput} | |||
|
595 | \begin{codeoutput} | |||
|
596 | \begin{verbatim} | |||
|
597 | 00_notebook_tour.ipynb formatting.ipynb | |||
|
598 | 01_notebook_introduction.ipynb octavemagic_extension.ipynb | |||
|
599 | Animations_and_Progress.ipynb publish_data.ipynb | |||
|
600 | Capturing Output.ipynb python-logo.svg | |||
|
601 | Script Magics.ipynb rmagic_extension.ipynb | |||
|
602 | animation.m4v sympy.ipynb | |||
|
603 | cython_extension.ipynb sympy_quantum_computing.ipynb | |||
|
604 | display_protocol.ipynb trapezoid_rule.ipynb | |||
|
605 | \end{verbatim} | |||
|
606 | \end{codeoutput} | |||
|
607 | \end{codecell} | |||
|
608 | If we want to create a link to one of them, we can call use the | |||
|
609 | \texttt{FileLink} object. | |||
|
610 | ||||
|
611 | \begin{codecell} | |||
|
612 | \begin{codeinput} | |||
|
613 | \begin{lstlisting} | |||
|
614 | from IPython.display import FileLink | |||
|
615 | FileLink('00_notebook_tour.ipynb') | |||
|
616 | \end{lstlisting} | |||
|
617 | \end{codeinput} | |||
|
618 | \begin{codeoutput} | |||
|
619 | \begin{verbatim} | |||
|
620 | <IPython.lib.display.FileLink at 0x10f7ea3d0> | |||
|
621 | \end{verbatim} | |||
|
622 | \end{codeoutput} | |||
|
623 | \end{codecell} | |||
|
624 | Alternatively, if we want to link to all of them, we can use the | |||
|
625 | \texttt{FileLinks} object, passing \texttt{'.'} to indicate that we want | |||
|
626 | links generated for the current working directory. Note that if there | |||
|
627 | were other directories under the current directory, \texttt{FileLinks} | |||
|
628 | would work in a recursive manner creating links to files in all | |||
|
629 | sub-directories as well. | |||
|
630 | ||||
|
631 | \begin{codecell} | |||
|
632 | \begin{codeinput} | |||
|
633 | \begin{lstlisting} | |||
|
634 | from IPython.display import FileLinks | |||
|
635 | FileLinks('.') | |||
|
636 | \end{lstlisting} | |||
|
637 | \end{codeinput} | |||
|
638 | \begin{codeoutput} | |||
|
639 | \begin{verbatim} | |||
|
640 | <IPython.lib.display.FileLinks at 0x10f7eaad0> | |||
|
641 | \end{verbatim} | |||
|
642 | \end{codeoutput} | |||
|
643 | \end{codecell} | |||
|
644 | \subsubsection{External sites} | |||
|
645 | ||||
|
646 | You can even embed an entire page from another site in an iframe; for | |||
|
647 | example this is today's Wikipedia page for mobile users: | |||
|
648 | ||||
|
649 | \begin{codecell} | |||
|
650 | \begin{codeinput} | |||
|
651 | \begin{lstlisting} | |||
|
652 | HTML('<iframe src=http://en.mobile.wikipedia.org/?useformat=mobile width=700 height=350></iframe>') | |||
|
653 | \end{lstlisting} | |||
|
654 | \end{codeinput} | |||
|
655 | \begin{codeoutput} | |||
|
656 | \begin{verbatim} | |||
|
657 | <IPython.core.display.HTML at 0x1094900d0> | |||
|
658 | \end{verbatim} | |||
|
659 | \end{codeoutput} | |||
|
660 | \end{codecell} | |||
|
661 | \subsubsection{Mathematics} | |||
|
662 | ||||
|
663 | And we also support the display of mathematical expressions typeset in | |||
|
664 | LaTeX, which is rendered in the browser thanks to the | |||
|
665 | \href{http://mathjax.org}{MathJax library}. | |||
|
666 | ||||
|
667 | Note that this is \emph{different} from the above examples. Above we | |||
|
668 | were typing mathematical expressions in Markdown cells (along with | |||
|
669 | normal text) and letting the browser render them; now we are displaying | |||
|
670 | the output of a Python computation as a LaTeX expression wrapped by the | |||
|
671 | \texttt{Math()} object so the browser renders it. The \texttt{Math} | |||
|
672 | object will add the needed LaTeX delimiters (\texttt{\$\$}) if they are | |||
|
673 | not provided: | |||
|
674 | ||||
|
675 | \begin{codecell} | |||
|
676 | \begin{codeinput} | |||
|
677 | \begin{lstlisting} | |||
|
678 | from IPython.display import Math | |||
|
679 | Math(r'F(k) = \int_{-\infty}^{\infty} f(x) e^{2\pi i k} dx') | |||
|
680 | \end{lstlisting} | |||
|
681 | \end{codeinput} | |||
|
682 | \begin{codeoutput} | |||
|
683 | \begin{equation*} | |||
|
684 | F(k) = \int_{-\infty}^{\infty} f(x) e^{2\pi i k} dx | |||
|
685 | \end{equation*} | |||
|
686 | \end{codeoutput} | |||
|
687 | \end{codecell} | |||
|
688 | With the \texttt{Latex} class, you have to include the delimiters | |||
|
689 | yourself. This allows you to use other LaTeX modes such as | |||
|
690 | \texttt{eqnarray}: | |||
|
691 | ||||
|
692 | \begin{codecell} | |||
|
693 | \begin{codeinput} | |||
|
694 | \begin{lstlisting} | |||
|
695 | from IPython.display import Latex | |||
|
696 | Latex(r"""\begin{eqnarray} | |||
|
697 | \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ | |||
|
698 | \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ | |||
|
699 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ | |||
|
700 | \nabla \cdot \vec{\mathbf{B}} & = 0 | |||
|
701 | \end{eqnarray}""") | |||
|
702 | \end{lstlisting} | |||
|
703 | \end{codeinput} | |||
|
704 | \begin{codeoutput} | |||
|
705 | \begin{equation*} | |||
|
706 | \begin{eqnarray} | |||
|
707 | \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ | |||
|
708 | \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ | |||
|
709 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ | |||
|
710 | \nabla \cdot \vec{\mathbf{B}} & = 0 | |||
|
711 | \end{eqnarray} | |||
|
712 | \end{equation*} | |||
|
713 | \end{codeoutput} | |||
|
714 | \end{codecell} | |||
|
715 | Or you can enter latex directly with the \texttt{\%\%latex} cell magic: | |||
|
716 | ||||
|
717 | \begin{codecell} | |||
|
718 | \begin{codeinput} | |||
|
719 | \begin{lstlisting} | |||
|
720 | %%latex | |||
|
721 | \begin{aligned} | |||
|
722 | \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ | |||
|
723 | \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ | |||
|
724 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ | |||
|
725 | \nabla \cdot \vec{\mathbf{B}} & = 0 | |||
|
726 | \end{aligned} | |||
|
727 | \end{lstlisting} | |||
|
728 | \end{codeinput} | |||
|
729 | \begin{codeoutput} | |||
|
730 | \begin{equation*} | |||
|
731 | \begin{aligned} | |||
|
732 | \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ | |||
|
733 | \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ | |||
|
734 | \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ | |||
|
735 | \nabla \cdot \vec{\mathbf{B}} & = 0 | |||
|
736 | \end{aligned} | |||
|
737 | \end{equation*} | |||
|
738 | \end{codeoutput} | |||
|
739 | \end{codecell} | |||
|
740 | There is also a \texttt{\%\%javascript} cell magic for running | |||
|
741 | javascript directly, and \texttt{\%\%svg} for manually entering SVG | |||
|
742 | content. | |||
|
743 | ||||
|
744 | \section{Loading external codes} | |||
|
745 | ||||
|
746 | \begin{itemize} | |||
|
747 | \item | |||
|
748 | Drag and drop a \texttt{.py} in the dashboard | |||
|
749 | \item | |||
|
750 | Use \texttt{\%load} with any local or remote url: | |||
|
751 | \href{http://matplotlib.sourceforge.net/gallery.html}{the Matplotlib | |||
|
752 | Gallery!} | |||
|
753 | \end{itemize} | |||
|
754 | In this notebook we've kept the output saved so you can see the result, | |||
|
755 | but you should run the next cell yourself (with an active internet | |||
|
756 | connection). | |||
|
757 | ||||
|
758 | Let's make sure we have pylab again, in case we have restarted the | |||
|
759 | kernel due to the crash demo above | |||
|
760 | ||||
|
761 | \begin{codecell} | |||
|
762 | \begin{codeinput} | |||
|
763 | \begin{lstlisting} | |||
|
764 | %pylab inline | |||
|
765 | \end{lstlisting} | |||
|
766 | \end{codeinput} | |||
|
767 | \begin{codeoutput} | |||
|
768 | \begin{verbatim} | |||
|
769 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
770 | For more information, type 'help(pylab)'. | |||
|
771 | \end{verbatim} | |||
|
772 | \end{codeoutput} | |||
|
773 | \end{codecell} | |||
|
774 | \begin{codecell} | |||
|
775 | \begin{codeinput} | |||
|
776 | \begin{lstlisting} | |||
|
777 | %load http://matplotlib.sourceforge.net/mpl_examples/pylab_examples/integral_demo.py | |||
|
778 | \end{lstlisting} | |||
|
779 | \end{codeinput} | |||
|
780 | \end{codecell} | |||
|
781 | \begin{codecell} | |||
|
782 | \begin{codeinput} | |||
|
783 | \begin{lstlisting} | |||
|
784 | #!/usr/bin/env python | |||
|
785 | ||||
|
786 | # implement the example graphs/integral from pyx | |||
|
787 | from pylab import * | |||
|
788 | from matplotlib.patches import Polygon | |||
|
789 | ||||
|
790 | def func(x): | |||
|
791 | return (x-3)*(x-5)*(x-7)+85 | |||
|
792 | ||||
|
793 | ax = subplot(111) | |||
|
794 | ||||
|
795 | a, b = 2, 9 # integral area | |||
|
796 | x = arange(0, 10, 0.01) | |||
|
797 | y = func(x) | |||
|
798 | plot(x, y, linewidth=1) | |||
|
799 | ||||
|
800 | # make the shaded region | |||
|
801 | ix = arange(a, b, 0.01) | |||
|
802 | iy = func(ix) | |||
|
803 | verts = [(a,0)] + zip(ix,iy) + [(b,0)] | |||
|
804 | poly = Polygon(verts, facecolor='0.8', edgecolor='k') | |||
|
805 | ax.add_patch(poly) | |||
|
806 | ||||
|
807 | text(0.5 * (a + b), 30, | |||
|
808 | r"$\int_a^b f(x)\mathrm{d}x$", horizontalalignment='center', | |||
|
809 | fontsize=20) | |||
|
810 | ||||
|
811 | axis([0,10, 0, 180]) | |||
|
812 | figtext(0.9, 0.05, 'x') | |||
|
813 | figtext(0.1, 0.9, 'y') | |||
|
814 | ax.set_xticks((a,b)) | |||
|
815 | ax.set_xticklabels(('a','b')) | |||
|
816 | ax.set_yticks([]) | |||
|
817 | show() | |||
|
818 | ||||
|
819 | \end{lstlisting} | |||
|
820 | \end{codeinput} | |||
|
821 | \begin{codeoutput} | |||
|
822 | \begin{center} | |||
|
823 | \includegraphics[width=0.7\textwidth]{00_notebook_tour_orig_files/00_notebook_tour_orig_fig_01.png} | |||
|
824 | \par | |||
|
825 | \end{center} | |||
|
826 | \end{codeoutput} | |||
|
827 | \end{codecell} | |||
|
828 | \end{document} |
@@ -0,0 +1,322 b'' | |||||
|
1 | # Some gun violence analysis with Wikipedia data | |||
|
2 | ||||
|
3 | As [requested by John Stokes](https://twitter.com/jonst0kes/status/282330530412888064), | |||
|
4 | here are per-capita numbers for gun-related homicides, | |||
|
5 | relating to GDP and total homicides, | |||
|
6 | so the situation in the United States can be put in context relative to other nations. | |||
|
7 | ||||
|
8 | main data source is UNODC (via Wikipedia [here](http://en.wikipedia.org/wiki/List_of_countries_by_intentional_homicide_rate) | |||
|
9 | and [here](http://en.wikipedia.org/wiki/List_of_countries_by_firearm-related_death_rate)). | |||
|
10 | ||||
|
11 | GDP data from World Bank, again [via Wikipedia](http://en.wikipedia.org/wiki/List_of_countries_by_GDP_(PPP)_per_capita). | |||
|
12 | ||||
|
13 | If the numbers on Wikipedia are inaccurate, or their relationship is not sound | |||
|
14 | (e.g. numbers taken from different years, during which significant change occured) | |||
|
15 | then obviously None of this analysis is valid. | |||
|
16 | ||||
|
17 | To summarize the data, | |||
|
18 | every possible way you look at it the US is lousy at preventing gun violence. | |||
|
19 | Even when compared to significantly more violent places, | |||
|
20 | gun violence in the US is a serious problem, | |||
|
21 | and when compared to similarly wealthy places, | |||
|
22 | the US is an outstanding disaster. | |||
|
23 | ||||
|
24 | **UPDATE:** the relationship of the gun data and totals does not seem to be valid. | |||
|
25 | [FBI data](http://www2.fbi.gov/ucr/cius2009/offenses/violent_crime/index.html) suggests that | |||
|
26 | the relative contribution of guns to homicides in the US is 47%, | |||
|
27 | but relating these two data sources gives 80%. | |||
|
28 | Internal comparisons should still be fine, but 'fraction' analysis has been stricken. | |||
|
29 | ||||
|
30 | <div class="highlight"><pre><span class="o">%</span><span class="k">load_ext</span> <span class="n">retina</span> | |||
|
31 | <span class="o">%</span><span class="k">pylab</span> <span class="n">inline</span> | |||
|
32 | </pre></div> | |||
|
33 | ||||
|
34 | ||||
|
35 | ||||
|
36 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
37 | For more information, type 'help(pylab)'. | |||
|
38 | ||||
|
39 | ||||
|
40 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">display</span> | |||
|
41 | <span class="kn">import</span> <span class="nn">pandas</span> | |||
|
42 | <span class="n">pandas</span><span class="o">.</span><span class="n">set_option</span><span class="p">(</span><span class="s">'display.notebook_repr_html'</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> | |||
|
43 | <span class="n">pandas</span><span class="o">.</span><span class="n">set_option</span><span class="p">(</span><span class="s">'display.precision'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> | |||
|
44 | </pre></div> | |||
|
45 | ||||
|
46 | ||||
|
47 | ||||
|
48 | Some utility functions for display | |||
|
49 | ||||
|
50 | <div class="highlight"><pre><span class="k">def</span> <span class="nf">plot_percent</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span> | |||
|
51 | <span class="n">df</span><span class="p">[</span><span class="s">'Gun Percent'</span><span class="p">][:</span><span class="n">limit</span><span class="p">]</span><span class="o">.</span><span class="n">plot</span><span class="p">()</span> | |||
|
52 | <span class="n">plt</span><span class="o">.</span><span class="n">ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">100</span><span class="p">)</span> | |||
|
53 | <span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s">"</span><span class="si">% G</span><span class="s">un Homicide"</span><span class="p">)</span> | |||
|
54 | <span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span> | |||
|
55 | </pre></div> | |||
|
56 | ||||
|
57 | ||||
|
58 | ||||
|
59 | <div class="highlight"><pre><span class="k">def</span> <span class="nf">plot_percapita</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span> | |||
|
60 | <span class="n">df</span> <span class="o">=</span> <span class="n">df</span><span class="o">.</span><span class="n">ix</span><span class="p">[:,[</span><span class="s">'Homicides'</span><span class="p">,</span> <span class="s">'Gun Homicides'</span><span class="p">]][:</span><span class="n">limit</span><span class="p">]</span> | |||
|
61 | <span class="n">df</span><span class="p">[</span><span class="s">'Total Homicides'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s">'Homicides'</span><span class="p">]</span> <span class="o">-</span> <span class="n">df</span><span class="p">[</span><span class="s">'Gun Homicides'</span><span class="p">]</span> | |||
|
62 | <span class="k">del</span> <span class="n">df</span><span class="p">[</span><span class="s">'Homicides'</span><span class="p">]</span> | |||
|
63 | <span class="n">df</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">kind</span><span class="o">=</span><span class="s">'bar'</span><span class="p">,</span> <span class="n">stacked</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">sort_columns</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> | |||
|
64 | <span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s">"per 100k"</span><span class="p">)</span> | |||
|
65 | <span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span> | |||
|
66 | </pre></div> | |||
|
67 | ||||
|
68 | ||||
|
69 | ||||
|
70 | <div class="highlight"><pre><span class="k">def</span> <span class="nf">display_relevant</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span> | |||
|
71 | <span class="n">display</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">ix</span><span class="p">[:,[</span><span class="s">'Homicides'</span><span class="p">,</span> <span class="s">'Gun Homicides'</span><span class="p">,</span> <span class="s">'Gun Data Source'</span><span class="p">]][:</span><span class="n">limit</span><span class="p">])</span> | |||
|
72 | </pre></div> | |||
|
73 | ||||
|
74 | ||||
|
75 | ||||
|
76 | Load the data | |||
|
77 | ||||
|
78 | <div class="highlight"><pre><span class="n">totals</span> <span class="o">=</span> <span class="n">pandas</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="s">'totals.csv'</span><span class="p">,</span> <span class="s">'</span><span class="se">\t</span><span class="s">'</span><span class="p">,</span> <span class="n">index_col</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> | |||
|
79 | <span class="n">guns</span> <span class="o">=</span> <span class="n">pandas</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="s">'guns.csv'</span><span class="p">,</span> <span class="s">'</span><span class="se">\t</span><span class="s">'</span><span class="p">,</span> <span class="n">index_col</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> | |||
|
80 | <span class="n">gdp</span> <span class="o">=</span> <span class="n">pandas</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="s">'gdp.csv'</span><span class="p">,</span> <span class="s">'</span><span class="se">\t</span><span class="s">'</span><span class="p">,</span> <span class="n">index_col</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> | |||
|
81 | <span class="n">data</span> <span class="o">=</span> <span class="n">totals</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">guns</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">gdp</span><span class="p">)</span> | |||
|
82 | <span class="n">data</span><span class="p">[</span><span class="s">'Gun Percent'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">*</span> <span class="n">data</span><span class="p">[</span><span class="s">'Gun Homicides'</span><span class="p">]</span> <span class="o">/</span> <span class="n">data</span><span class="p">[</span><span class="s">'Homicides'</span><span class="p">]</span> | |||
|
83 | <span class="k">del</span> <span class="n">data</span><span class="p">[</span><span class="s">'Unintentional'</span><span class="p">],</span><span class="n">data</span><span class="p">[</span><span class="s">'Undetermined'</span><span class="p">],</span><span class="n">data</span><span class="p">[</span><span class="s">'Gun Suicides'</span><span class="p">]</span> | |||
|
84 | <span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span> | |||
|
85 | </pre></div> | |||
|
86 | ||||
|
87 | ||||
|
88 | ||||
|
89 | Of all sampled countries (Found data for 68 countries), | |||
|
90 | the US is in the top 15 in Gun Homicides per capita. | |||
|
91 | ||||
|
92 | Numbers are per 100k. | |||
|
93 | ||||
|
94 | <div class="highlight"><pre><span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="s">"Gun Homicides"</span><span class="p">,</span> <span class="n">ascending</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span> | |||
|
95 | <span class="n">display_relevant</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span> | |||
|
96 | </pre></div> | |||
|
97 | ||||
|
98 | ||||
|
99 | Homicides Gun Homicides Gun Data Source | |||
|
100 | Country | |||
|
101 | El Salvador 69.2 50.4 OAS 2011[1] | |||
|
102 | Jamaica 52.2 47.4 OAS 2011[1] | |||
|
103 | Honduras 91.6 46.7 OAS 2011[1] | |||
|
104 | Guatemala 38.5 38.5 OAS 2011[1] | |||
|
105 | Colombia 33.4 27.1 UNODC 2011 [2] | |||
|
106 | Brazil 21.0 18.1 UNODC 2011[3] | |||
|
107 | Panama 21.6 12.9 OAS 2011[1] | |||
|
108 | Mexico 16.9 10.0 UNODC 2011[4] | |||
|
109 | Paraguay 11.5 7.3 UNODC 2000[11] | |||
|
110 | Nicaragua 13.6 7.1 OAS 2011[1] | |||
|
111 | United States 4.2 3.7 OAS 2012[5][6] | |||
|
112 | Costa Rica 10.0 3.3 UNODC 2002[7] | |||
|
113 | Uruguay 5.9 3.2 UNODC 2002[7] | |||
|
114 | Argentina 3.4 3.0 UNODC 2011[12] | |||
|
115 | Barbados 11.3 3.0 UNODC 2000[11] | |||
|
116 | ||||
|
117 | Take top 30 Countries by GDP | |||
|
118 | ||||
|
119 | <div class="highlight"><pre><span class="n">top</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="s">'GDP'</span><span class="p">)[</span><span class="o">-</span><span class="mi">30</span><span class="p">:]</span> | |||
|
120 | </pre></div> | |||
|
121 | ||||
|
122 | ||||
|
123 | ||||
|
124 | and rank them by Gun Homicides per capita: | |||
|
125 | ||||
|
126 | <div class="highlight"><pre><span class="n">top_by_guns</span> <span class="o">=</span> <span class="n">top</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="s">"Gun Homicides"</span><span class="p">,</span> <span class="n">ascending</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span> | |||
|
127 | <span class="n">display_relevant</span><span class="p">(</span><span class="n">top_by_guns</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> | |||
|
128 | <span class="n">plot_percapita</span><span class="p">(</span><span class="n">top_by_guns</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> | |||
|
129 | </pre></div> | |||
|
130 | ||||
|
131 | ||||
|
132 | Homicides Gun Homicides Gun Data Source | |||
|
133 | Country | |||
|
134 | United States 4.2 3.7 OAS 2012[5][6] | |||
|
135 | Israel 2.1 0.9 WHO 2012[10] | |||
|
136 | Canada 1.6 0.8 Krug 1998[13] | |||
|
137 | Luxembourg 2.5 0.6 WHO 2012[10] | |||
|
138 | Greece 1.5 0.6 Krug 1998[13] | |||
|
139 | ||||
|
140 | ![](tests/ipynbref/Gun_Data_orig_files/Gun_Data_orig_fig_00.png) | |||
|
141 | ||||
|
142 | ||||
|
143 | **NOTE:** these bar graphs should not be interpreted as fractions of a total, | |||
|
144 | as the two data sources do not appear to be comparable. | |||
|
145 | But the red and blue bar graphs should still be internally comparable. | |||
|
146 | ||||
|
147 | The US is easily #1 of 30 wealthiest countries in Gun Homicides per capita, | |||
|
148 | by a factor of 4:1 | |||
|
149 | ||||
|
150 | Adding USA, Canada, and Mexico to all of Europe, | |||
|
151 | USA is a strong #2 behind Mexico in total gun homicides per-capita | |||
|
152 | ||||
|
153 | <div class="highlight"><pre><span class="n">index</span> <span class="o">=</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s">'Region'</span><span class="p">]</span> <span class="o">==</span> <span class="s">'Europe'</span><span class="p">)</span> <span class="o">+</span> \ | |||
|
154 | <span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">index</span> <span class="o">==</span> <span class="s">'United States'</span><span class="p">)</span> <span class="o">+</span> \ | |||
|
155 | <span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">index</span> <span class="o">==</span> <span class="s">'Canada'</span><span class="p">)</span> <span class="o">+</span> \ | |||
|
156 | <span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">index</span> <span class="o">==</span> <span class="s">'Mexico'</span><span class="p">)</span> | |||
|
157 | <span class="n">selected</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> | |||
|
158 | ||||
|
159 | <span class="k">print</span> <span class="s">"By Total Gun Homicides"</span> | |||
|
160 | <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span> | |||
|
161 | ||||
|
162 | <span class="n">by_guns</span> <span class="o">=</span> <span class="n">selected</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="s">"Gun Homicides"</span><span class="p">,</span> <span class="n">ascending</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span> | |||
|
163 | <span class="c">#by_guns['Gun Homicides'].plot(kind='bar')</span> | |||
|
164 | <span class="n">plot_percapita</span><span class="p">(</span><span class="n">by_guns</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="mi">25</span><span class="p">)</span> | |||
|
165 | <span class="n">display_relevant</span><span class="p">(</span><span class="n">selected</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span> | |||
|
166 | </pre></div> | |||
|
167 | ||||
|
168 | ||||
|
169 | By Total Gun Homicides | |||
|
170 | ||||
|
171 | ||||
|
172 | ![](tests/ipynbref/Gun_Data_orig_files/Gun_Data_orig_fig_01.png) | |||
|
173 | ||||
|
174 | Homicides Gun Homicides Gun Data Source | |||
|
175 | Country | |||
|
176 | Mexico 16.9 10.0 UNODC 2011[4] | |||
|
177 | United States 4.2 3.7 OAS 2012[5][6] | |||
|
178 | Montenegro 3.5 2.1 WHO 2012[10] | |||
|
179 | Moldova 7.5 1.0 WHO 2012[10] | |||
|
180 | Canada 1.6 0.8 Krug 1998[13] | |||
|
181 | Serbia 1.2 0.6 WHO 2012[10] | |||
|
182 | Luxembourg 2.5 0.6 WHO 2012[10] | |||
|
183 | Greece 1.5 0.6 Krug 1998[13] | |||
|
184 | Croatia 1.4 0.6 WHO 2012[10] | |||
|
185 | Switzerland 0.7 0.5 OAS 2011[1] | |||
|
186 | Malta 1.0 0.5 WHO 2012[10] | |||
|
187 | Portugal 1.2 0.5 WHO 2012[10] | |||
|
188 | Belarus 4.9 0.4 UNODC 2002[7] | |||
|
189 | Ireland 1.2 0.4 WHO 2012[10] | |||
|
190 | Italy 0.9 0.4 WHO 2012[10] | |||
|
191 | Ukraine 5.2 0.3 UNODC 2000[11] | |||
|
192 | Estonia 5.2 0.3 WHO 2012[10] | |||
|
193 | Belgium 1.7 0.3 WHO 2012[10] | |||
|
194 | Finland 2.2 0.3 WHO 2012[10] | |||
|
195 | Lithuania 6.6 0.2 WHO 2012[10] | |||
|
196 | Bulgaria 2.0 0.2 WHO 2012[10] | |||
|
197 | Georgia 4.3 0.2 WHO 2012[10] | |||
|
198 | Denmark 0.9 0.2 WHO 2012[10] | |||
|
199 | France 1.1 0.2 WHO 2012[10] | |||
|
200 | Netherlands 1.1 0.2 WHO 2012[10] | |||
|
201 | Sweden 1.0 0.2 WHO 2012[10] | |||
|
202 | Slovakia 1.5 0.2 WHO 2012[10] | |||
|
203 | Austria 0.6 0.2 WHO 2012[10] | |||
|
204 | Latvia 3.1 0.2 WHO 2012[10] | |||
|
205 | Spain 0.8 0.1 WHO 2012[10] | |||
|
206 | Hungary 1.3 0.1 WHO 2012[10] | |||
|
207 | Czech Republic 1.7 0.1 WHO 2012[10] | |||
|
208 | Germany 0.8 0.1 WHO 2012[10] | |||
|
209 | Slovenia 0.7 0.1 WHO 2012[10] | |||
|
210 | Romania 2.0 0.0 WHO 2012[10] | |||
|
211 | United Kingdom 1.2 0.0 WHO2012 [10] | |||
|
212 | Norway 0.6 0.0 WHO 2012[10] | |||
|
213 | Poland 1.1 0.0 WHO 2012[10] | |||
|
214 | ||||
|
215 | Let's just compare US, Canada, and UK: | |||
|
216 | ||||
|
217 | <div class="highlight"><pre><span class="n">select</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">ix</span><span class="p">[[</span><span class="s">'United States'</span><span class="p">,</span> <span class="s">'Canada'</span><span class="p">,</span> <span class="s">'United Kingdom'</span><span class="p">]]</span> | |||
|
218 | <span class="n">plot_percapita</span><span class="p">(</span><span class="n">select</span><span class="p">)</span> | |||
|
219 | </pre></div> | |||
|
220 | ||||
|
221 | ||||
|
222 | ||||
|
223 | ![](tests/ipynbref/Gun_Data_orig_files/Gun_Data_orig_fig_02.png) | |||
|
224 | ||||
|
225 | ||||
|
226 | Normalize to the US numbers (inverse) | |||
|
227 | ||||
|
228 | <div class="highlight"><pre><span class="n">select</span><span class="p">[</span><span class="s">'Homicides'</span><span class="p">]</span> <span class="o">=</span> <span class="n">select</span><span class="p">[</span><span class="s">'Homicides'</span><span class="p">][</span><span class="s">'United States'</span><span class="p">]</span> <span class="o">/</span> <span class="n">select</span><span class="p">[</span><span class="s">'Homicides'</span><span class="p">]</span> | |||
|
229 | <span class="n">select</span><span class="p">[</span><span class="s">'Gun Homicides'</span><span class="p">]</span> <span class="o">=</span> <span class="n">select</span><span class="p">[</span><span class="s">'Gun Homicides'</span><span class="p">][</span><span class="s">'United States'</span><span class="p">]</span> <span class="o">/</span> <span class="n">select</span><span class="p">[</span><span class="s">'Gun Homicides'</span><span class="p">]</span> | |||
|
230 | <span class="n">display_relevant</span><span class="p">(</span><span class="n">select</span><span class="p">)</span> | |||
|
231 | </pre></div> | |||
|
232 | ||||
|
233 | ||||
|
234 | Homicides Gun Homicides Gun Data Source | |||
|
235 | United States 1.0 1.0 OAS 2012[5][6] | |||
|
236 | Canada 2.6 4.9 Krug 1998[13] | |||
|
237 | United Kingdom 3.5 92.5 WHO2012 [10] | |||
|
238 | ||||
|
239 | So, you are 2.6 times more likely to be killed in the US than Canada, | |||
|
240 | and 3.5 times more likely than in the UK. | |||
|
241 | That's bad, but not extreme. | |||
|
242 | ||||
|
243 | However, you are 4.9 times more likely to be killed *with a gun* in the US than Canada, | |||
|
244 | and almost 100 times more likely than in the UK. That is pretty extreme. | |||
|
245 | ||||
|
246 | ||||
|
247 | Countries represented: | |||
|
248 | ||||
|
249 | <div class="highlight"><pre><span class="k">for</span> <span class="n">country</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">index</span><span class="p">:</span> | |||
|
250 | <span class="k">print</span> <span class="n">country</span> | |||
|
251 | </pre></div> | |||
|
252 | ||||
|
253 | ||||
|
254 | El Salvador | |||
|
255 | Jamaica | |||
|
256 | Honduras | |||
|
257 | Guatemala | |||
|
258 | Colombia | |||
|
259 | Brazil | |||
|
260 | Panama | |||
|
261 | Mexico | |||
|
262 | Paraguay | |||
|
263 | Nicaragua | |||
|
264 | United States | |||
|
265 | Costa Rica | |||
|
266 | Uruguay | |||
|
267 | Argentina | |||
|
268 | Barbados | |||
|
269 | Montenegro | |||
|
270 | Peru | |||
|
271 | Moldova | |||
|
272 | Israel | |||
|
273 | India | |||
|
274 | Canada | |||
|
275 | Serbia | |||
|
276 | Luxembourg | |||
|
277 | Greece | |||
|
278 | Uzbekistan | |||
|
279 | Croatia | |||
|
280 | Kyrgyzstan | |||
|
281 | Switzerland | |||
|
282 | Malta | |||
|
283 | Portugal | |||
|
284 | Belarus | |||
|
285 | Ireland | |||
|
286 | Italy | |||
|
287 | Kuwait | |||
|
288 | Ukraine | |||
|
289 | Estonia | |||
|
290 | Belgium | |||
|
291 | Finland | |||
|
292 | Lithuania | |||
|
293 | Cyprus | |||
|
294 | Bulgaria | |||
|
295 | Georgia | |||
|
296 | Denmark | |||
|
297 | France | |||
|
298 | Netherlands | |||
|
299 | Sweden | |||
|
300 | Slovakia | |||
|
301 | Qatar | |||
|
302 | Austria | |||
|
303 | Latvia | |||
|
304 | New Zealand | |||
|
305 | Spain | |||
|
306 | Hungary | |||
|
307 | Czech Republic | |||
|
308 | Hong Kong | |||
|
309 | Australia | |||
|
310 | Singapore | |||
|
311 | Chile | |||
|
312 | Germany | |||
|
313 | Slovenia | |||
|
314 | Romania | |||
|
315 | Azerbaijan | |||
|
316 | South Korea | |||
|
317 | United Kingdom | |||
|
318 | Norway | |||
|
319 | Japan | |||
|
320 | Poland | |||
|
321 | Mauritius | |||
|
322 |
@@ -0,0 +1,304 b'' | |||||
|
1 | ## Some gun violence analysis with Wikipedia data | |||
|
2 | ||||
|
3 | # As [requested by John Stokes](https://twitter.com/jonst0kes/status/282330530412888064), | |||
|
4 | # here are per-capita numbers for gun-related homicides, | |||
|
5 | # relating to GDP and total homicides, | |||
|
6 | # so the situation in the United States can be put in context relative to other nations. | |||
|
7 | ||||
|
8 | # main data source is UNODC (via Wikipedia [here](http://en.wikipedia.org/wiki/List_of_countries_by_intentional_homicide_rate) | |||
|
9 | # and [here](http://en.wikipedia.org/wiki/List_of_countries_by_firearm-related_death_rate)). | |||
|
10 | # | |||
|
11 | # GDP data from World Bank, again [via Wikipedia](http://en.wikipedia.org/wiki/List_of_countries_by_GDP_(PPP)_per_capita). | |||
|
12 | # | |||
|
13 | # If the numbers on Wikipedia are inaccurate, or their relationship is not sound | |||
|
14 | # (e.g. numbers taken from different years, during which significant change occured) | |||
|
15 | # then obviously None of this analysis is valid. | |||
|
16 | # | |||
|
17 | # To summarize the data, | |||
|
18 | # every possible way you look at it the US is lousy at preventing gun violence. | |||
|
19 | # Even when compared to significantly more violent places, | |||
|
20 | # gun violence in the US is a serious problem, | |||
|
21 | # and when compared to similarly wealthy places, | |||
|
22 | # the US is an outstanding disaster. | |||
|
23 | ||||
|
24 | # **UPDATE:** the relationship of the gun data and totals does not seem to be valid. | |||
|
25 | # [FBI data](http://www2.fbi.gov/ucr/cius2009/offenses/violent_crime/index.html) suggests that | |||
|
26 | # the relative contribution of guns to homicides in the US is 47%, | |||
|
27 | # but relating these two data sources gives 80%. | |||
|
28 | # Internal comparisons should still be fine, but 'fraction' analysis has been stricken. | |||
|
29 | ||||
|
30 | # In[1]: | |||
|
31 | %load_ext retina | |||
|
32 | %pylab inline | |||
|
33 | ||||
|
34 | # Out[1]: | |||
|
35 | # | |||
|
36 | # Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
37 | # For more information, type 'help(pylab)'. | |||
|
38 | # | |||
|
39 | # In[2]: | |||
|
40 | from IPython.display import display | |||
|
41 | import pandas | |||
|
42 | pandas.set_option('display.notebook_repr_html', True) | |||
|
43 | pandas.set_option('display.precision', 2) | |||
|
44 | ||||
|
45 | # Some utility functions for display | |||
|
46 | ||||
|
47 | # In[3]: | |||
|
48 | def plot_percent(df, limit=10): | |||
|
49 | df['Gun Percent'][:limit].plot() | |||
|
50 | plt.ylim(0,100) | |||
|
51 | plt.title("% Gun Homicide") | |||
|
52 | plt.show() | |||
|
53 | ||||
|
54 | ||||
|
55 | # In[4]: | |||
|
56 | def plot_percapita(df, limit=10): | |||
|
57 | df = df.ix[:,['Homicides', 'Gun Homicides']][:limit] | |||
|
58 | df['Total Homicides'] = df['Homicides'] - df['Gun Homicides'] | |||
|
59 | del df['Homicides'] | |||
|
60 | df.plot(kind='bar', stacked=True, sort_columns=True) | |||
|
61 | plt.ylabel("per 100k") | |||
|
62 | plt.show() | |||
|
63 | ||||
|
64 | ||||
|
65 | # In[8]: | |||
|
66 | def display_relevant(df, limit=10): | |||
|
67 | display(df.ix[:,['Homicides', 'Gun Homicides', 'Gun Data Source']][:limit]) | |||
|
68 | ||||
|
69 | # Load the data | |||
|
70 | ||||
|
71 | # In[9]: | |||
|
72 | totals = pandas.read_csv('totals.csv', '\t', index_col=0) | |||
|
73 | guns = pandas.read_csv('guns.csv', '\t', index_col=0) | |||
|
74 | gdp = pandas.read_csv('gdp.csv', '\t', index_col=1) | |||
|
75 | data = totals.join(guns).join(gdp) | |||
|
76 | data['Gun Percent'] = 100 * data['Gun Homicides'] / data['Homicides'] | |||
|
77 | del data['Unintentional'],data['Undetermined'],data['Gun Suicides'] | |||
|
78 | data = data.dropna() | |||
|
79 | ||||
|
80 | # Of all sampled countries (Found data for 68 countries), | |||
|
81 | # the US is in the top 15 in Gun Homicides per capita. | |||
|
82 | # | |||
|
83 | # Numbers are per 100k. | |||
|
84 | ||||
|
85 | # In[10]: | |||
|
86 | data = data.sort("Gun Homicides", ascending=False) | |||
|
87 | display_relevant(data, 15) | |||
|
88 | ||||
|
89 | # Out[10]: | |||
|
90 | # Homicides Gun Homicides Gun Data Source | |||
|
91 | # Country | |||
|
92 | # El Salvador 69.2 50.4 OAS 2011[1] | |||
|
93 | # Jamaica 52.2 47.4 OAS 2011[1] | |||
|
94 | # Honduras 91.6 46.7 OAS 2011[1] | |||
|
95 | # Guatemala 38.5 38.5 OAS 2011[1] | |||
|
96 | # Colombia 33.4 27.1 UNODC 2011 [2] | |||
|
97 | # Brazil 21.0 18.1 UNODC 2011[3] | |||
|
98 | # Panama 21.6 12.9 OAS 2011[1] | |||
|
99 | # Mexico 16.9 10.0 UNODC 2011[4] | |||
|
100 | # Paraguay 11.5 7.3 UNODC 2000[11] | |||
|
101 | # Nicaragua 13.6 7.1 OAS 2011[1] | |||
|
102 | # United States 4.2 3.7 OAS 2012[5][6] | |||
|
103 | # Costa Rica 10.0 3.3 UNODC 2002[7] | |||
|
104 | # Uruguay 5.9 3.2 UNODC 2002[7] | |||
|
105 | # Argentina 3.4 3.0 UNODC 2011[12] | |||
|
106 | # Barbados 11.3 3.0 UNODC 2000[11] | |||
|
107 | # Take top 30 Countries by GDP | |||
|
108 | ||||
|
109 | # In[11]: | |||
|
110 | top = data.sort('GDP')[-30:] | |||
|
111 | ||||
|
112 | # and rank them by Gun Homicides per capita: | |||
|
113 | ||||
|
114 | # In[12]: | |||
|
115 | top_by_guns = top.sort("Gun Homicides", ascending=False) | |||
|
116 | display_relevant(top_by_guns, 5) | |||
|
117 | plot_percapita(top_by_guns, 10) | |||
|
118 | ||||
|
119 | # Out[12]: | |||
|
120 | # Homicides Gun Homicides Gun Data Source | |||
|
121 | # Country | |||
|
122 | # United States 4.2 3.7 OAS 2012[5][6] | |||
|
123 | # Israel 2.1 0.9 WHO 2012[10] | |||
|
124 | # Canada 1.6 0.8 Krug 1998[13] | |||
|
125 | # Luxembourg 2.5 0.6 WHO 2012[10] | |||
|
126 | # Greece 1.5 0.6 Krug 1998[13] | |||
|
127 | # image file: tests/ipynbref/Gun_Data_orig_files/Gun_Data_orig_fig_00.png | |||
|
128 | ||||
|
129 | # **NOTE:** these bar graphs should not be interpreted as fractions of a total, | |||
|
130 | # as the two data sources do not appear to be comparable. | |||
|
131 | # But the red and blue bar graphs should still be internally comparable. | |||
|
132 | ||||
|
133 | # The US is easily #1 of 30 wealthiest countries in Gun Homicides per capita, | |||
|
134 | # by a factor of 4:1 | |||
|
135 | ||||
|
136 | # Adding USA, Canada, and Mexico to all of Europe, | |||
|
137 | # USA is a strong #2 behind Mexico in total gun homicides per-capita | |||
|
138 | ||||
|
139 | # In[13]: | |||
|
140 | index = (data['Region'] == 'Europe') + \ | |||
|
141 | (data.index == 'United States') + \ | |||
|
142 | (data.index == 'Canada') + \ | |||
|
143 | (data.index == 'Mexico') | |||
|
144 | selected = data[index] | |||
|
145 | ||||
|
146 | print "By Total Gun Homicides" | |||
|
147 | sys.stdout.flush() | |||
|
148 | ||||
|
149 | by_guns = selected.sort("Gun Homicides", ascending=False) | |||
|
150 | #by_guns['Gun Homicides'].plot(kind='bar') | |||
|
151 | plot_percapita(by_guns, limit=25) | |||
|
152 | display_relevant(selected, limit=None) | |||
|
153 | ||||
|
154 | ||||
|
155 | # Out[13]: | |||
|
156 | # By Total Gun Homicides | |||
|
157 | # | |||
|
158 | # image file: tests/ipynbref/Gun_Data_orig_files/Gun_Data_orig_fig_01.png | |||
|
159 | ||||
|
160 | # Homicides Gun Homicides Gun Data Source | |||
|
161 | # Country | |||
|
162 | # Mexico 16.9 10.0 UNODC 2011[4] | |||
|
163 | # United States 4.2 3.7 OAS 2012[5][6] | |||
|
164 | # Montenegro 3.5 2.1 WHO 2012[10] | |||
|
165 | # Moldova 7.5 1.0 WHO 2012[10] | |||
|
166 | # Canada 1.6 0.8 Krug 1998[13] | |||
|
167 | # Serbia 1.2 0.6 WHO 2012[10] | |||
|
168 | # Luxembourg 2.5 0.6 WHO 2012[10] | |||
|
169 | # Greece 1.5 0.6 Krug 1998[13] | |||
|
170 | # Croatia 1.4 0.6 WHO 2012[10] | |||
|
171 | # Switzerland 0.7 0.5 OAS 2011[1] | |||
|
172 | # Malta 1.0 0.5 WHO 2012[10] | |||
|
173 | # Portugal 1.2 0.5 WHO 2012[10] | |||
|
174 | # Belarus 4.9 0.4 UNODC 2002[7] | |||
|
175 | # Ireland 1.2 0.4 WHO 2012[10] | |||
|
176 | # Italy 0.9 0.4 WHO 2012[10] | |||
|
177 | # Ukraine 5.2 0.3 UNODC 2000[11] | |||
|
178 | # Estonia 5.2 0.3 WHO 2012[10] | |||
|
179 | # Belgium 1.7 0.3 WHO 2012[10] | |||
|
180 | # Finland 2.2 0.3 WHO 2012[10] | |||
|
181 | # Lithuania 6.6 0.2 WHO 2012[10] | |||
|
182 | # Bulgaria 2.0 0.2 WHO 2012[10] | |||
|
183 | # Georgia 4.3 0.2 WHO 2012[10] | |||
|
184 | # Denmark 0.9 0.2 WHO 2012[10] | |||
|
185 | # France 1.1 0.2 WHO 2012[10] | |||
|
186 | # Netherlands 1.1 0.2 WHO 2012[10] | |||
|
187 | # Sweden 1.0 0.2 WHO 2012[10] | |||
|
188 | # Slovakia 1.5 0.2 WHO 2012[10] | |||
|
189 | # Austria 0.6 0.2 WHO 2012[10] | |||
|
190 | # Latvia 3.1 0.2 WHO 2012[10] | |||
|
191 | # Spain 0.8 0.1 WHO 2012[10] | |||
|
192 | # Hungary 1.3 0.1 WHO 2012[10] | |||
|
193 | # Czech Republic 1.7 0.1 WHO 2012[10] | |||
|
194 | # Germany 0.8 0.1 WHO 2012[10] | |||
|
195 | # Slovenia 0.7 0.1 WHO 2012[10] | |||
|
196 | # Romania 2.0 0.0 WHO 2012[10] | |||
|
197 | # United Kingdom 1.2 0.0 WHO2012 [10] | |||
|
198 | # Norway 0.6 0.0 WHO 2012[10] | |||
|
199 | # Poland 1.1 0.0 WHO 2012[10] | |||
|
200 | # Let's just compare US, Canada, and UK: | |||
|
201 | ||||
|
202 | # In[15]: | |||
|
203 | select = data.ix[['United States', 'Canada', 'United Kingdom']] | |||
|
204 | plot_percapita(select) | |||
|
205 | ||||
|
206 | # Out[15]: | |||
|
207 | # image file: tests/ipynbref/Gun_Data_orig_files/Gun_Data_orig_fig_02.png | |||
|
208 | ||||
|
209 | # Normalize to the US numbers (inverse) | |||
|
210 | ||||
|
211 | # In[16]: | |||
|
212 | select['Homicides'] = select['Homicides']['United States'] / select['Homicides'] | |||
|
213 | select['Gun Homicides'] = select['Gun Homicides']['United States'] / select['Gun Homicides'] | |||
|
214 | display_relevant(select) | |||
|
215 | ||||
|
216 | # Out[16]: | |||
|
217 | # Homicides Gun Homicides Gun Data Source | |||
|
218 | # United States 1.0 1.0 OAS 2012[5][6] | |||
|
219 | # Canada 2.6 4.9 Krug 1998[13] | |||
|
220 | # United Kingdom 3.5 92.5 WHO2012 [10] | |||
|
221 | # So, you are 2.6 times more likely to be killed in the US than Canada, | |||
|
222 | # and 3.5 times more likely than in the UK. | |||
|
223 | # That's bad, but not extreme. | |||
|
224 | # | |||
|
225 | # However, you are 4.9 times more likely to be killed *with a gun* in the US than Canada, | |||
|
226 | # and almost 100 times more likely than in the UK. That is pretty extreme. | |||
|
227 | # | |||
|
228 | ||||
|
229 | # Countries represented: | |||
|
230 | ||||
|
231 | # In[14]: | |||
|
232 | for country in data.index: | |||
|
233 | print country | |||
|
234 | ||||
|
235 | # Out[14]: | |||
|
236 | # El Salvador | |||
|
237 | # Jamaica | |||
|
238 | # Honduras | |||
|
239 | # Guatemala | |||
|
240 | # Colombia | |||
|
241 | # Brazil | |||
|
242 | # Panama | |||
|
243 | # Mexico | |||
|
244 | # Paraguay | |||
|
245 | # Nicaragua | |||
|
246 | # United States | |||
|
247 | # Costa Rica | |||
|
248 | # Uruguay | |||
|
249 | # Argentina | |||
|
250 | # Barbados | |||
|
251 | # Montenegro | |||
|
252 | # Peru | |||
|
253 | # Moldova | |||
|
254 | # Israel | |||
|
255 | # India | |||
|
256 | # Canada | |||
|
257 | # Serbia | |||
|
258 | # Luxembourg | |||
|
259 | # Greece | |||
|
260 | # Uzbekistan | |||
|
261 | # Croatia | |||
|
262 | # Kyrgyzstan | |||
|
263 | # Switzerland | |||
|
264 | # Malta | |||
|
265 | # Portugal | |||
|
266 | # Belarus | |||
|
267 | # Ireland | |||
|
268 | # Italy | |||
|
269 | # Kuwait | |||
|
270 | # Ukraine | |||
|
271 | # Estonia | |||
|
272 | # Belgium | |||
|
273 | # Finland | |||
|
274 | # Lithuania | |||
|
275 | # Cyprus | |||
|
276 | # Bulgaria | |||
|
277 | # Georgia | |||
|
278 | # Denmark | |||
|
279 | # France | |||
|
280 | # Netherlands | |||
|
281 | # Sweden | |||
|
282 | # Slovakia | |||
|
283 | # Qatar | |||
|
284 | # Austria | |||
|
285 | # Latvia | |||
|
286 | # New Zealand | |||
|
287 | # Spain | |||
|
288 | # Hungary | |||
|
289 | # Czech Republic | |||
|
290 | # Hong Kong | |||
|
291 | # Australia | |||
|
292 | # Singapore | |||
|
293 | # Chile | |||
|
294 | # Germany | |||
|
295 | # Slovenia | |||
|
296 | # Romania | |||
|
297 | # Azerbaijan | |||
|
298 | # South Korea | |||
|
299 | # United Kingdom | |||
|
300 | # Norway | |||
|
301 | # Japan | |||
|
302 | # Poland | |||
|
303 | # Mauritius | |||
|
304 | # No newline at end of file |
This diff has been collapsed as it changes many lines, (505 lines changed) Show them Hide them | |||||
@@ -0,0 +1,505 b'' | |||||
|
1 | %% This file was auto-generated by IPython. | |||
|
2 | %% Conversion from the original notebook file: | |||
|
3 | %% tests/ipynbref/Gun_Data.orig.ipynb | |||
|
4 | %% | |||
|
5 | \documentclass[11pt,english]{article} | |||
|
6 | ||||
|
7 | %% This is the automatic preamble used by IPython. Note that it does *not* | |||
|
8 | %% include a documentclass declaration, that is added at runtime to the overall | |||
|
9 | %% document. | |||
|
10 | ||||
|
11 | \usepackage{amsmath} | |||
|
12 | \usepackage{amssymb} | |||
|
13 | \usepackage{graphicx} | |||
|
14 | \usepackage{ucs} | |||
|
15 | \usepackage[utf8x]{inputenc} | |||
|
16 | ||||
|
17 | % needed for markdown enumerations to work | |||
|
18 | \usepackage{enumerate} | |||
|
19 | ||||
|
20 | % Slightly bigger margins than the latex defaults | |||
|
21 | \usepackage{geometry} | |||
|
22 | \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm} | |||
|
23 | ||||
|
24 | % Define a few colors for use in code, links and cell shading | |||
|
25 | \usepackage{color} | |||
|
26 | \definecolor{orange}{cmyk}{0,0.4,0.8,0.2} | |||
|
27 | \definecolor{darkorange}{rgb}{.71,0.21,0.01} | |||
|
28 | \definecolor{darkgreen}{rgb}{.12,.54,.11} | |||
|
29 | \definecolor{myteal}{rgb}{.26, .44, .56} | |||
|
30 | \definecolor{gray}{gray}{0.45} | |||
|
31 | \definecolor{lightgray}{gray}{.95} | |||
|
32 | \definecolor{mediumgray}{gray}{.8} | |||
|
33 | \definecolor{inputbackground}{rgb}{.95, .95, .85} | |||
|
34 | \definecolor{outputbackground}{rgb}{.95, .95, .95} | |||
|
35 | \definecolor{traceback}{rgb}{1, .95, .95} | |||
|
36 | ||||
|
37 | % Framed environments for code cells (inputs, outputs, errors, ...). The | |||
|
38 | % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't | |||
|
39 | % randomly change them unless you're sure of the effect it will have. | |||
|
40 | \usepackage{framed} | |||
|
41 | ||||
|
42 | % remove extraneous vertical space in boxes | |||
|
43 | \setlength\fboxsep{0pt} | |||
|
44 | ||||
|
45 | % codecell is the whole input+output set of blocks that a Code cell can | |||
|
46 | % generate. | |||
|
47 | ||||
|
48 | % TODO: unfortunately, it seems that using a framed codecell environment breaks | |||
|
49 | % the ability of the frames inside of it to be broken across pages. This | |||
|
50 | % causes at least the problem of having lots of empty space at the bottom of | |||
|
51 | % pages as new frames are moved to the next page, and if a single frame is too | |||
|
52 | % long to fit on a page, will completely stop latex from compiling the | |||
|
53 | % document. So unless we figure out a solution to this, we'll have to instead | |||
|
54 | % leave the codecell env. as empty. I'm keeping the original codecell | |||
|
55 | % definition here (a thin vertical bar) for reference, in case we find a | |||
|
56 | % solution to the page break issue. | |||
|
57 | ||||
|
58 | %% \newenvironment{codecell}{% | |||
|
59 | %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}% | |||
|
60 | %% \MakeFramed{\vspace{-0.5em}}} | |||
|
61 | %% {\unskip\endMakeFramed} | |||
|
62 | ||||
|
63 | % For now, make this a no-op... | |||
|
64 | \newenvironment{codecell}{} | |||
|
65 | ||||
|
66 | \newenvironment{codeinput}{% | |||
|
67 | \def\FrameCommand{\colorbox{inputbackground}}% | |||
|
68 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
69 | {\unskip\endMakeFramed} | |||
|
70 | ||||
|
71 | \newenvironment{codeoutput}{% | |||
|
72 | \def\FrameCommand{\colorbox{outputbackground}}% | |||
|
73 | \vspace{-1.4em} | |||
|
74 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
75 | {\unskip\medskip\endMakeFramed} | |||
|
76 | ||||
|
77 | \newenvironment{traceback}{% | |||
|
78 | \def\FrameCommand{\colorbox{traceback}}% | |||
|
79 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
80 | {\endMakeFramed} | |||
|
81 | ||||
|
82 | % Use and configure listings package for nicely formatted code | |||
|
83 | \usepackage{listingsutf8} | |||
|
84 | \lstset{ | |||
|
85 | language=python, | |||
|
86 | inputencoding=utf8x, | |||
|
87 | extendedchars=\true, | |||
|
88 | aboveskip=\smallskipamount, | |||
|
89 | belowskip=\smallskipamount, | |||
|
90 | xleftmargin=2mm, | |||
|
91 | breaklines=true, | |||
|
92 | basicstyle=\small \ttfamily, | |||
|
93 | showstringspaces=false, | |||
|
94 | keywordstyle=\color{blue}\bfseries, | |||
|
95 | commentstyle=\color{myteal}, | |||
|
96 | stringstyle=\color{darkgreen}, | |||
|
97 | identifierstyle=\color{darkorange}, | |||
|
98 | columns=fullflexible, % tighter character kerning, like verb | |||
|
99 | } | |||
|
100 | ||||
|
101 | % The hyperref package gives us a pdf with properly built | |||
|
102 | % internal navigation ('pdf bookmarks' for the table of contents, | |||
|
103 | % internal cross-reference links, web links for URLs, etc.) | |||
|
104 | \usepackage{hyperref} | |||
|
105 | \hypersetup{ | |||
|
106 | breaklinks=true, % so long urls are correctly broken across lines | |||
|
107 | colorlinks=true, | |||
|
108 | urlcolor=blue, | |||
|
109 | linkcolor=darkorange, | |||
|
110 | citecolor=darkgreen, | |||
|
111 | } | |||
|
112 | ||||
|
113 | % hardcode size of all verbatim environments to be a bit smaller | |||
|
114 | \makeatletter | |||
|
115 | \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt | |||
|
116 | \makeatother | |||
|
117 | ||||
|
118 | % Prevent overflowing lines due to urls and other hard-to-break entities. | |||
|
119 | \sloppy | |||
|
120 | ||||
|
121 | \begin{document} | |||
|
122 | ||||
|
123 | \section{Some gun violence analysis with Wikipedia data} | |||
|
124 | As | |||
|
125 | \href{https://twitter.com/jonst0kes/status/282330530412888064}{requested | |||
|
126 | by John Stokes}, here are per-capita numbers for gun-related homicides, | |||
|
127 | relating to GDP and total homicides, so the situation in the United | |||
|
128 | States can be put in context relative to other nations. | |||
|
129 | ||||
|
130 | main data source is UNODC (via Wikipedia | |||
|
131 | \href{http://en.wikipedia.org/wiki/List\_of\_countries\_by\_intentional\_homicide\_rate}{here} | |||
|
132 | and | |||
|
133 | \href{http://en.wikipedia.org/wiki/List\_of\_countries\_by\_firearm-related\_death\_rate}{here}). | |||
|
134 | ||||
|
135 | GDP data from World Bank, again | |||
|
136 | \href{http://en.wikipedia.org/wiki/List\_of\_countries\_by\_GDP\_(PPP)\_per\_capita}{via | |||
|
137 | Wikipedia}. | |||
|
138 | ||||
|
139 | If the numbers on Wikipedia are inaccurate, or their relationship is not | |||
|
140 | sound (e.g.~numbers taken from different years, during which significant | |||
|
141 | change occured) then obviously None of this analysis is valid. | |||
|
142 | ||||
|
143 | To summarize the data, every possible way you look at it the US is lousy | |||
|
144 | at preventing gun violence. Even when compared to significantly more | |||
|
145 | violent places, gun violence in the US is a serious problem, and when | |||
|
146 | compared to similarly wealthy places, the US is an outstanding disaster. | |||
|
147 | ||||
|
148 | \textbf{UPDATE:} the relationship of the gun data and totals does not | |||
|
149 | seem to be valid. | |||
|
150 | \href{http://www2.fbi.gov/ucr/cius2009/offenses/violent\_crime/index.html}{FBI | |||
|
151 | data} suggests that the relative contribution of guns to homicides in | |||
|
152 | the US is 47\%, but relating these two data sources gives 80\%. Internal | |||
|
153 | comparisons should still be fine, but `fraction' analysis has been | |||
|
154 | stricken. | |||
|
155 | ||||
|
156 | \begin{codecell} | |||
|
157 | \begin{codeinput} | |||
|
158 | \begin{lstlisting} | |||
|
159 | %load_ext retina | |||
|
160 | %pylab inline | |||
|
161 | \end{lstlisting} | |||
|
162 | \end{codeinput} | |||
|
163 | \begin{codeoutput} | |||
|
164 | \begin{verbatim} | |||
|
165 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
166 | For more information, type 'help(pylab)'. | |||
|
167 | \end{verbatim} | |||
|
168 | \end{codeoutput} | |||
|
169 | \end{codecell} | |||
|
170 | \begin{codecell} | |||
|
171 | \begin{codeinput} | |||
|
172 | \begin{lstlisting} | |||
|
173 | from IPython.display import display | |||
|
174 | import pandas | |||
|
175 | pandas.set_option('display.notebook_repr_html', True) | |||
|
176 | pandas.set_option('display.precision', 2) | |||
|
177 | \end{lstlisting} | |||
|
178 | \end{codeinput} | |||
|
179 | \end{codecell} | |||
|
180 | Some utility functions for display | |||
|
181 | ||||
|
182 | \begin{codecell} | |||
|
183 | \begin{codeinput} | |||
|
184 | \begin{lstlisting} | |||
|
185 | def plot_percent(df, limit=10): | |||
|
186 | df['Gun Percent'][:limit].plot() | |||
|
187 | plt.ylim(0,100) | |||
|
188 | plt.title("% Gun Homicide") | |||
|
189 | plt.show() | |||
|
190 | ||||
|
191 | \end{lstlisting} | |||
|
192 | \end{codeinput} | |||
|
193 | \end{codecell} | |||
|
194 | \begin{codecell} | |||
|
195 | \begin{codeinput} | |||
|
196 | \begin{lstlisting} | |||
|
197 | def plot_percapita(df, limit=10): | |||
|
198 | df = df.ix[:,['Homicides', 'Gun Homicides']][:limit] | |||
|
199 | df['Total Homicides'] = df['Homicides'] - df['Gun Homicides'] | |||
|
200 | del df['Homicides'] | |||
|
201 | df.plot(kind='bar', stacked=True, sort_columns=True) | |||
|
202 | plt.ylabel("per 100k") | |||
|
203 | plt.show() | |||
|
204 | ||||
|
205 | \end{lstlisting} | |||
|
206 | \end{codeinput} | |||
|
207 | \end{codecell} | |||
|
208 | \begin{codecell} | |||
|
209 | \begin{codeinput} | |||
|
210 | \begin{lstlisting} | |||
|
211 | def display_relevant(df, limit=10): | |||
|
212 | display(df.ix[:,['Homicides', 'Gun Homicides', 'Gun Data Source']][:limit]) | |||
|
213 | \end{lstlisting} | |||
|
214 | \end{codeinput} | |||
|
215 | \end{codecell} | |||
|
216 | Load the data | |||
|
217 | ||||
|
218 | \begin{codecell} | |||
|
219 | \begin{codeinput} | |||
|
220 | \begin{lstlisting} | |||
|
221 | totals = pandas.read_csv('totals.csv', '\t', index_col=0) | |||
|
222 | guns = pandas.read_csv('guns.csv', '\t', index_col=0) | |||
|
223 | gdp = pandas.read_csv('gdp.csv', '\t', index_col=1) | |||
|
224 | data = totals.join(guns).join(gdp) | |||
|
225 | data['Gun Percent'] = 100 * data['Gun Homicides'] / data['Homicides'] | |||
|
226 | del data['Unintentional'],data['Undetermined'],data['Gun Suicides'] | |||
|
227 | data = data.dropna() | |||
|
228 | \end{lstlisting} | |||
|
229 | \end{codeinput} | |||
|
230 | \end{codecell} | |||
|
231 | Of all sampled countries (Found data for 68 countries), the US is in the | |||
|
232 | top 15 in Gun Homicides per capita. | |||
|
233 | ||||
|
234 | Numbers are per 100k. | |||
|
235 | ||||
|
236 | \begin{codecell} | |||
|
237 | \begin{codeinput} | |||
|
238 | \begin{lstlisting} | |||
|
239 | data = data.sort("Gun Homicides", ascending=False) | |||
|
240 | display_relevant(data, 15) | |||
|
241 | \end{lstlisting} | |||
|
242 | \end{codeinput} | |||
|
243 | \begin{codeoutput} | |||
|
244 | \begin{verbatim} | |||
|
245 | Homicides Gun Homicides Gun Data Source | |||
|
246 | Country | |||
|
247 | El Salvador 69.2 50.4 OAS 2011[1] | |||
|
248 | Jamaica 52.2 47.4 OAS 2011[1] | |||
|
249 | Honduras 91.6 46.7 OAS 2011[1] | |||
|
250 | Guatemala 38.5 38.5 OAS 2011[1] | |||
|
251 | Colombia 33.4 27.1 UNODC 2011 [2] | |||
|
252 | Brazil 21.0 18.1 UNODC 2011[3] | |||
|
253 | Panama 21.6 12.9 OAS 2011[1] | |||
|
254 | Mexico 16.9 10.0 UNODC 2011[4] | |||
|
255 | Paraguay 11.5 7.3 UNODC 2000[11] | |||
|
256 | Nicaragua 13.6 7.1 OAS 2011[1] | |||
|
257 | United States 4.2 3.7 OAS 2012[5][6] | |||
|
258 | Costa Rica 10.0 3.3 UNODC 2002[7] | |||
|
259 | Uruguay 5.9 3.2 UNODC 2002[7] | |||
|
260 | Argentina 3.4 3.0 UNODC 2011[12] | |||
|
261 | Barbados 11.3 3.0 UNODC 2000[11] | |||
|
262 | \end{verbatim} | |||
|
263 | \end{codeoutput} | |||
|
264 | \end{codecell} | |||
|
265 | Take top 30 Countries by GDP | |||
|
266 | ||||
|
267 | \begin{codecell} | |||
|
268 | \begin{codeinput} | |||
|
269 | \begin{lstlisting} | |||
|
270 | top = data.sort('GDP')[-30:] | |||
|
271 | \end{lstlisting} | |||
|
272 | \end{codeinput} | |||
|
273 | \end{codecell} | |||
|
274 | and rank them by Gun Homicides per capita: | |||
|
275 | ||||
|
276 | \begin{codecell} | |||
|
277 | \begin{codeinput} | |||
|
278 | \begin{lstlisting} | |||
|
279 | top_by_guns = top.sort("Gun Homicides", ascending=False) | |||
|
280 | display_relevant(top_by_guns, 5) | |||
|
281 | plot_percapita(top_by_guns, 10) | |||
|
282 | \end{lstlisting} | |||
|
283 | \end{codeinput} | |||
|
284 | \begin{codeoutput} | |||
|
285 | \begin{verbatim} | |||
|
286 | Homicides Gun Homicides Gun Data Source | |||
|
287 | Country | |||
|
288 | United States 4.2 3.7 OAS 2012[5][6] | |||
|
289 | Israel 2.1 0.9 WHO 2012[10] | |||
|
290 | Canada 1.6 0.8 Krug 1998[13] | |||
|
291 | Luxembourg 2.5 0.6 WHO 2012[10] | |||
|
292 | Greece 1.5 0.6 Krug 1998[13] | |||
|
293 | \end{verbatim} | |||
|
294 | \begin{center} | |||
|
295 | \includegraphics[width=0.7\textwidth]{Gun_Data_orig_files/Gun_Data_orig_fig_00.png} | |||
|
296 | \par | |||
|
297 | \end{center} | |||
|
298 | \end{codeoutput} | |||
|
299 | \end{codecell} | |||
|
300 | \textbf{NOTE:} these bar graphs should not be interpreted as fractions | |||
|
301 | of a total, as the two data sources do not appear to be comparable. But | |||
|
302 | the red and blue bar graphs should still be internally comparable. | |||
|
303 | ||||
|
304 | The US is easily \#1 of 30 wealthiest countries in Gun Homicides per | |||
|
305 | capita, by a factor of 4:1 | |||
|
306 | ||||
|
307 | Adding USA, Canada, and Mexico to all of Europe, USA is a strong \#2 | |||
|
308 | behind Mexico in total gun homicides per-capita | |||
|
309 | ||||
|
310 | \begin{codecell} | |||
|
311 | \begin{codeinput} | |||
|
312 | \begin{lstlisting} | |||
|
313 | index = (data['Region'] == 'Europe') + \ | |||
|
314 | (data.index == 'United States') + \ | |||
|
315 | (data.index == 'Canada') + \ | |||
|
316 | (data.index == 'Mexico') | |||
|
317 | selected = data[index] | |||
|
318 | ||||
|
319 | print "By Total Gun Homicides" | |||
|
320 | sys.stdout.flush() | |||
|
321 | ||||
|
322 | by_guns = selected.sort("Gun Homicides", ascending=False) | |||
|
323 | #by_guns['Gun Homicides'].plot(kind='bar') | |||
|
324 | plot_percapita(by_guns, limit=25) | |||
|
325 | display_relevant(selected, limit=None) | |||
|
326 | ||||
|
327 | \end{lstlisting} | |||
|
328 | \end{codeinput} | |||
|
329 | \begin{codeoutput} | |||
|
330 | \begin{verbatim} | |||
|
331 | By Total Gun Homicides | |||
|
332 | \end{verbatim} | |||
|
333 | \begin{center} | |||
|
334 | \includegraphics[width=0.7\textwidth]{Gun_Data_orig_files/Gun_Data_orig_fig_01.png} | |||
|
335 | \par | |||
|
336 | \end{center} | |||
|
337 | \begin{verbatim} | |||
|
338 | Homicides Gun Homicides Gun Data Source | |||
|
339 | Country | |||
|
340 | Mexico 16.9 10.0 UNODC 2011[4] | |||
|
341 | United States 4.2 3.7 OAS 2012[5][6] | |||
|
342 | Montenegro 3.5 2.1 WHO 2012[10] | |||
|
343 | Moldova 7.5 1.0 WHO 2012[10] | |||
|
344 | Canada 1.6 0.8 Krug 1998[13] | |||
|
345 | Serbia 1.2 0.6 WHO 2012[10] | |||
|
346 | Luxembourg 2.5 0.6 WHO 2012[10] | |||
|
347 | Greece 1.5 0.6 Krug 1998[13] | |||
|
348 | Croatia 1.4 0.6 WHO 2012[10] | |||
|
349 | Switzerland 0.7 0.5 OAS 2011[1] | |||
|
350 | Malta 1.0 0.5 WHO 2012[10] | |||
|
351 | Portugal 1.2 0.5 WHO 2012[10] | |||
|
352 | Belarus 4.9 0.4 UNODC 2002[7] | |||
|
353 | Ireland 1.2 0.4 WHO 2012[10] | |||
|
354 | Italy 0.9 0.4 WHO 2012[10] | |||
|
355 | Ukraine 5.2 0.3 UNODC 2000[11] | |||
|
356 | Estonia 5.2 0.3 WHO 2012[10] | |||
|
357 | Belgium 1.7 0.3 WHO 2012[10] | |||
|
358 | Finland 2.2 0.3 WHO 2012[10] | |||
|
359 | Lithuania 6.6 0.2 WHO 2012[10] | |||
|
360 | Bulgaria 2.0 0.2 WHO 2012[10] | |||
|
361 | Georgia 4.3 0.2 WHO 2012[10] | |||
|
362 | Denmark 0.9 0.2 WHO 2012[10] | |||
|
363 | France 1.1 0.2 WHO 2012[10] | |||
|
364 | Netherlands 1.1 0.2 WHO 2012[10] | |||
|
365 | Sweden 1.0 0.2 WHO 2012[10] | |||
|
366 | Slovakia 1.5 0.2 WHO 2012[10] | |||
|
367 | Austria 0.6 0.2 WHO 2012[10] | |||
|
368 | Latvia 3.1 0.2 WHO 2012[10] | |||
|
369 | Spain 0.8 0.1 WHO 2012[10] | |||
|
370 | Hungary 1.3 0.1 WHO 2012[10] | |||
|
371 | Czech Republic 1.7 0.1 WHO 2012[10] | |||
|
372 | Germany 0.8 0.1 WHO 2012[10] | |||
|
373 | Slovenia 0.7 0.1 WHO 2012[10] | |||
|
374 | Romania 2.0 0.0 WHO 2012[10] | |||
|
375 | United Kingdom 1.2 0.0 WHO2012 [10] | |||
|
376 | Norway 0.6 0.0 WHO 2012[10] | |||
|
377 | Poland 1.1 0.0 WHO 2012[10] | |||
|
378 | \end{verbatim} | |||
|
379 | \end{codeoutput} | |||
|
380 | \end{codecell} | |||
|
381 | Let's just compare US, Canada, and UK: | |||
|
382 | ||||
|
383 | \begin{codecell} | |||
|
384 | \begin{codeinput} | |||
|
385 | \begin{lstlisting} | |||
|
386 | select = data.ix[['United States', 'Canada', 'United Kingdom']] | |||
|
387 | plot_percapita(select) | |||
|
388 | \end{lstlisting} | |||
|
389 | \end{codeinput} | |||
|
390 | \begin{codeoutput} | |||
|
391 | \begin{center} | |||
|
392 | \includegraphics[width=0.7\textwidth]{Gun_Data_orig_files/Gun_Data_orig_fig_02.png} | |||
|
393 | \par | |||
|
394 | \end{center} | |||
|
395 | \end{codeoutput} | |||
|
396 | \end{codecell} | |||
|
397 | Normalize to the US numbers (inverse) | |||
|
398 | ||||
|
399 | \begin{codecell} | |||
|
400 | \begin{codeinput} | |||
|
401 | \begin{lstlisting} | |||
|
402 | select['Homicides'] = select['Homicides']['United States'] / select['Homicides'] | |||
|
403 | select['Gun Homicides'] = select['Gun Homicides']['United States'] / select['Gun Homicides'] | |||
|
404 | display_relevant(select) | |||
|
405 | \end{lstlisting} | |||
|
406 | \end{codeinput} | |||
|
407 | \begin{codeoutput} | |||
|
408 | \begin{verbatim} | |||
|
409 | Homicides Gun Homicides Gun Data Source | |||
|
410 | United States 1.0 1.0 OAS 2012[5][6] | |||
|
411 | Canada 2.6 4.9 Krug 1998[13] | |||
|
412 | United Kingdom 3.5 92.5 WHO2012 [10] | |||
|
413 | \end{verbatim} | |||
|
414 | \end{codeoutput} | |||
|
415 | \end{codecell} | |||
|
416 | So, you are 2.6 times more likely to be killed in the US than Canada, | |||
|
417 | and 3.5 times more likely than in the UK. That's bad, but not extreme. | |||
|
418 | ||||
|
419 | However, you are 4.9 times more likely to be killed \emph{with a gun} in | |||
|
420 | the US than Canada, and almost 100 times more likely than in the UK. | |||
|
421 | That is pretty extreme. | |||
|
422 | ||||
|
423 | Countries represented: | |||
|
424 | ||||
|
425 | \begin{codecell} | |||
|
426 | \begin{codeinput} | |||
|
427 | \begin{lstlisting} | |||
|
428 | for country in data.index: | |||
|
429 | print country | |||
|
430 | \end{lstlisting} | |||
|
431 | \end{codeinput} | |||
|
432 | \begin{codeoutput} | |||
|
433 | \begin{verbatim} | |||
|
434 | El Salvador | |||
|
435 | Jamaica | |||
|
436 | Honduras | |||
|
437 | Guatemala | |||
|
438 | Colombia | |||
|
439 | Brazil | |||
|
440 | Panama | |||
|
441 | Mexico | |||
|
442 | Paraguay | |||
|
443 | Nicaragua | |||
|
444 | United States | |||
|
445 | Costa Rica | |||
|
446 | Uruguay | |||
|
447 | Argentina | |||
|
448 | Barbados | |||
|
449 | Montenegro | |||
|
450 | Peru | |||
|
451 | Moldova | |||
|
452 | Israel | |||
|
453 | India | |||
|
454 | Canada | |||
|
455 | Serbia | |||
|
456 | Luxembourg | |||
|
457 | Greece | |||
|
458 | Uzbekistan | |||
|
459 | Croatia | |||
|
460 | Kyrgyzstan | |||
|
461 | Switzerland | |||
|
462 | Malta | |||
|
463 | Portugal | |||
|
464 | Belarus | |||
|
465 | Ireland | |||
|
466 | Italy | |||
|
467 | Kuwait | |||
|
468 | Ukraine | |||
|
469 | Estonia | |||
|
470 | Belgium | |||
|
471 | Finland | |||
|
472 | Lithuania | |||
|
473 | Cyprus | |||
|
474 | Bulgaria | |||
|
475 | Georgia | |||
|
476 | Denmark | |||
|
477 | France | |||
|
478 | Netherlands | |||
|
479 | Sweden | |||
|
480 | Slovakia | |||
|
481 | Qatar | |||
|
482 | Austria | |||
|
483 | Latvia | |||
|
484 | New Zealand | |||
|
485 | Spain | |||
|
486 | Hungary | |||
|
487 | Czech Republic | |||
|
488 | Hong Kong | |||
|
489 | Australia | |||
|
490 | Singapore | |||
|
491 | Chile | |||
|
492 | Germany | |||
|
493 | Slovenia | |||
|
494 | Romania | |||
|
495 | Azerbaijan | |||
|
496 | South Korea | |||
|
497 | United Kingdom | |||
|
498 | Norway | |||
|
499 | Japan | |||
|
500 | Poland | |||
|
501 | Mauritius | |||
|
502 | \end{verbatim} | |||
|
503 | \end{codeoutput} | |||
|
504 | \end{codecell} | |||
|
505 | \end{document} |
@@ -0,0 +1,460 b'' | |||||
|
1 | # XKCD plots in Matplotlib | |||
|
2 | ||||
|
3 | This notebook originally appeared as a blog post at [Pythonic Perambulations](http://jakevdp.github.com/blog/2012/10/07/xkcd-style-plots-in-matplotlib/) by Jake Vanderplas. | |||
|
4 | ||||
|
5 | One of the problems I've had with typical matplotlib figures is that everything in them is so precise, so perfect. For an example of what I mean, take a look at this figure: | |||
|
6 | ||||
|
7 | <div class="highlight"><pre><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">Image</span> | |||
|
8 | <span class="n">Image</span><span class="p">(</span><span class="s">'http://jakevdp.github.com/figures/xkcd_version.png'</span><span class="p">)</span> | |||
|
9 | </pre></div> | |||
|
10 | ||||
|
11 | ||||
|
12 | <pre> | |||
|
13 | <IPython.core.display.Image at 0x2fef710> | |||
|
14 | </pre> | |||
|
15 | ||||
|
16 | ||||
|
17 | Sometimes when showing schematic plots, this is the type of figure I want to display. But drawing it by hand is a pain: I'd rather just use matplotlib. The problem is, matplotlib is a bit too precise. Attempting to duplicate this figure in matplotlib leads to something like this: | |||
|
18 | ||||
|
19 | <div class="highlight"><pre><span class="n">Image</span><span class="p">(</span><span class="s">'http://jakevdp.github.com/figures/mpl_version.png'</span><span class="p">)</span> | |||
|
20 | </pre></div> | |||
|
21 | ||||
|
22 | ||||
|
23 | <pre> | |||
|
24 | <IPython.core.display.Image at 0x2fef0d0> | |||
|
25 | </pre> | |||
|
26 | ||||
|
27 | ||||
|
28 | It just doesn't have the same effect. Matplotlib is great for scientific plots, but sometimes you don't want to be so precise. | |||
|
29 | ||||
|
30 | This subject has recently come up on the matplotlib mailing list, and started some interesting discussions. | |||
|
31 | As near as I can tell, this started with a thread on a | |||
|
32 | [mathematica list](http://mathematica.stackexchange.com/questions/11350/xkcd-style-graphs) | |||
|
33 | which prompted a thread on the [matplotlib list](http://matplotlib.1069221.n5.nabble.com/XKCD-style-graphs-td39226.html) | |||
|
34 | wondering if the same could be done in matplotlib. | |||
|
35 | ||||
|
36 | Damon McDougall offered a quick | |||
|
37 | [solution](http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg25499.html) | |||
|
38 | which was improved by Fernando Perez in [this notebook](http://nbviewer.ipython.org/3835181/), and | |||
|
39 | within a few days there was a [matplotlib pull request](https://github.com/matplotlib/matplotlib/pull/1329) offering a very general | |||
|
40 | way to create sketch-style plots in matplotlib. Only a few days from a cool idea to a | |||
|
41 | working implementation: this is one of the most incredible aspects of package development on github. | |||
|
42 | ||||
|
43 | The pull request looks really nice, but will likely not be included in a released version of | |||
|
44 | matplotlib until at least version 1.3. In the mean-time, I wanted a way to play around with | |||
|
45 | these types of plots in a way that is compatible with the current release of matplotlib. To do that, | |||
|
46 | I created the following code: | |||
|
47 | ||||
|
48 | ## The Code: XKCDify | |||
|
49 | ||||
|
50 | XKCDify will take a matplotlib ``Axes`` instance, and modify the plot elements in-place to make | |||
|
51 | them look hand-drawn. | |||
|
52 | First off, we'll need to make sure we have the Humor Sans font. | |||
|
53 | It can be downloaded using the command below. | |||
|
54 | ||||
|
55 | Next we'll create a function ``xkcd_line`` to add jitter to lines. We want this to be very general, so | |||
|
56 | we'll normalize the size of the lines, and use a low-pass filter to add correlated noise, perpendicular | |||
|
57 | to the direction of the line. There are a few parameters for this filter that can be tweaked to | |||
|
58 | customize the appearance of the jitter. | |||
|
59 | ||||
|
60 | Finally, we'll create a function which accepts a matplotlib axis, and calls ``xkcd_line`` on | |||
|
61 | all lines in the axis. Additionally, we'll switch the font of all text in the axes, and add | |||
|
62 | some background lines for a nice effect where lines cross. We'll also draw axes, and move the | |||
|
63 | axes labels and titles to the appropriate location. | |||
|
64 | ||||
|
65 | <div class="highlight"><pre><span class="sd">"""</span> | |||
|
66 | <span class="sd">XKCD plot generator</span> | |||
|
67 | <span class="sd">-------------------</span> | |||
|
68 | <span class="sd">Author: Jake Vanderplas</span> | |||
|
69 | ||||
|
70 | <span class="sd">This is a script that will take any matplotlib line diagram, and convert it</span> | |||
|
71 | <span class="sd">to an XKCD-style plot. It will work for plots with line & text elements,</span> | |||
|
72 | <span class="sd">including axes labels and titles (but not axes tick labels).</span> | |||
|
73 | ||||
|
74 | <span class="sd">The idea for this comes from work by Damon McDougall</span> | |||
|
75 | <span class="sd"> http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg25499.html</span> | |||
|
76 | <span class="sd">"""</span> | |||
|
77 | <span class="kn">import</span> <span class="nn">numpy</span> <span class="kn">as</span> <span class="nn">np</span> | |||
|
78 | <span class="kn">import</span> <span class="nn">pylab</span> <span class="kn">as</span> <span class="nn">pl</span> | |||
|
79 | <span class="kn">from</span> <span class="nn">scipy</span> <span class="kn">import</span> <span class="n">interpolate</span><span class="p">,</span> <span class="n">signal</span> | |||
|
80 | <span class="kn">import</span> <span class="nn">matplotlib.font_manager</span> <span class="kn">as</span> <span class="nn">fm</span> | |||
|
81 | ||||
|
82 | ||||
|
83 | <span class="c"># We need a special font for the code below. It can be downloaded this way:</span> | |||
|
84 | <span class="kn">import</span> <span class="nn">os</span> | |||
|
85 | <span class="kn">import</span> <span class="nn">urllib2</span> | |||
|
86 | <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="s">'Humor-Sans.ttf'</span><span class="p">):</span> | |||
|
87 | <span class="n">fhandle</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s">'http://antiyawn.com/uploads/Humor-Sans.ttf'</span><span class="p">)</span> | |||
|
88 | <span class="nb">open</span><span class="p">(</span><span class="s">'Humor-Sans.ttf'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">fhandle</span><span class="o">.</span><span class="n">read</span><span class="p">())</span> | |||
|
89 | ||||
|
90 | ||||
|
91 | <span class="k">def</span> <span class="nf">xkcd_line</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">xlim</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">ylim</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> | |||
|
92 | <span class="n">mag</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">f1</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">f2</span><span class="o">=</span><span class="mf">0.05</span><span class="p">,</span> <span class="n">f3</span><span class="o">=</span><span class="mi">15</span><span class="p">):</span> | |||
|
93 | <span class="sd">"""</span> | |||
|
94 | <span class="sd"> Mimic a hand-drawn line from (x, y) data</span> | |||
|
95 | ||||
|
96 | <span class="sd"> Parameters</span> | |||
|
97 | <span class="sd"> ----------</span> | |||
|
98 | <span class="sd"> x, y : array_like</span> | |||
|
99 | <span class="sd"> arrays to be modified</span> | |||
|
100 | <span class="sd"> xlim, ylim : data range</span> | |||
|
101 | <span class="sd"> the assumed plot range for the modification. If not specified,</span> | |||
|
102 | <span class="sd"> they will be guessed from the data</span> | |||
|
103 | <span class="sd"> mag : float</span> | |||
|
104 | <span class="sd"> magnitude of distortions</span> | |||
|
105 | <span class="sd"> f1, f2, f3 : int, float, int</span> | |||
|
106 | <span class="sd"> filtering parameters. f1 gives the size of the window, f2 gives</span> | |||
|
107 | <span class="sd"> the high-frequency cutoff, f3 gives the size of the filter</span> | |||
|
108 | <span class="sd"> </span> | |||
|
109 | <span class="sd"> Returns</span> | |||
|
110 | <span class="sd"> -------</span> | |||
|
111 | <span class="sd"> x, y : ndarrays</span> | |||
|
112 | <span class="sd"> The modified lines</span> | |||
|
113 | <span class="sd"> """</span> | |||
|
114 | <span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> | |||
|
115 | <span class="n">y</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> | |||
|
116 | ||||
|
117 | <span class="c"># get limits for rescaling</span> | |||
|
118 | <span class="k">if</span> <span class="n">xlim</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> | |||
|
119 | <span class="n">xlim</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">min</span><span class="p">(),</span> <span class="n">x</span><span class="o">.</span><span class="n">max</span><span class="p">())</span> | |||
|
120 | <span class="k">if</span> <span class="n">ylim</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> | |||
|
121 | <span class="n">ylim</span> <span class="o">=</span> <span class="p">(</span><span class="n">y</span><span class="o">.</span><span class="n">min</span><span class="p">(),</span> <span class="n">y</span><span class="o">.</span><span class="n">max</span><span class="p">())</span> | |||
|
122 | ||||
|
123 | <span class="k">if</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span> | |||
|
124 | <span class="n">xlim</span> <span class="o">=</span> <span class="n">ylim</span> | |||
|
125 | ||||
|
126 | <span class="k">if</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span> | |||
|
127 | <span class="n">ylim</span> <span class="o">=</span> <span class="n">xlim</span> | |||
|
128 | ||||
|
129 | <span class="c"># scale the data</span> | |||
|
130 | <span class="n">x_scaled</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">*</span> <span class="mf">1.</span> <span class="o">/</span> <span class="p">(</span><span class="n">xlim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> | |||
|
131 | <span class="n">y_scaled</span> <span class="o">=</span> <span class="p">(</span><span class="n">y</span> <span class="o">-</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">*</span> <span class="mf">1.</span> <span class="o">/</span> <span class="p">(</span><span class="n">ylim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> | |||
|
132 | ||||
|
133 | <span class="c"># compute the total distance along the path</span> | |||
|
134 | <span class="n">dx</span> <span class="o">=</span> <span class="n">x_scaled</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">-</span> <span class="n">x_scaled</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> | |||
|
135 | <span class="n">dy</span> <span class="o">=</span> <span class="n">y_scaled</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">-</span> <span class="n">y_scaled</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> | |||
|
136 | <span class="n">dist_tot</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">dx</span> <span class="o">*</span> <span class="n">dx</span> <span class="o">+</span> <span class="n">dy</span> <span class="o">*</span> <span class="n">dy</span><span class="p">))</span> | |||
|
137 | ||||
|
138 | <span class="c"># number of interpolated points is proportional to the distance</span> | |||
|
139 | <span class="n">Nu</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="mi">200</span> <span class="o">*</span> <span class="n">dist_tot</span><span class="p">)</span> | |||
|
140 | <span class="n">u</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">Nu</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mf">1.</span> <span class="o">/</span> <span class="p">(</span><span class="n">Nu</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> | |||
|
141 | ||||
|
142 | <span class="c"># interpolate curve at sampled points</span> | |||
|
143 | <span class="n">k</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> | |||
|
144 | <span class="n">res</span> <span class="o">=</span> <span class="n">interpolate</span><span class="o">.</span><span class="n">splprep</span><span class="p">([</span><span class="n">x_scaled</span><span class="p">,</span> <span class="n">y_scaled</span><span class="p">],</span> <span class="n">s</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="n">k</span><span class="p">)</span> | |||
|
145 | <span class="n">x_int</span><span class="p">,</span> <span class="n">y_int</span> <span class="o">=</span> <span class="n">interpolate</span><span class="o">.</span><span class="n">splev</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">res</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> | |||
|
146 | ||||
|
147 | <span class="c"># we'll perturb perpendicular to the drawn line</span> | |||
|
148 | <span class="n">dx</span> <span class="o">=</span> <span class="n">x_int</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span> <span class="o">-</span> <span class="n">x_int</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> | |||
|
149 | <span class="n">dy</span> <span class="o">=</span> <span class="n">y_int</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span> <span class="o">-</span> <span class="n">y_int</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> | |||
|
150 | <span class="n">dist</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">dx</span> <span class="o">*</span> <span class="n">dx</span> <span class="o">+</span> <span class="n">dy</span> <span class="o">*</span> <span class="n">dy</span><span class="p">)</span> | |||
|
151 | ||||
|
152 | <span class="c"># create a filtered perturbation</span> | |||
|
153 | <span class="n">coeffs</span> <span class="o">=</span> <span class="n">mag</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">normal</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.01</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">x_int</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> | |||
|
154 | <span class="n">b</span> <span class="o">=</span> <span class="n">signal</span><span class="o">.</span><span class="n">firwin</span><span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">f2</span> <span class="o">*</span> <span class="n">dist_tot</span><span class="p">,</span> <span class="n">window</span><span class="o">=</span><span class="p">(</span><span class="s">'kaiser'</span><span class="p">,</span> <span class="n">f3</span><span class="p">))</span> | |||
|
155 | <span class="n">response</span> <span class="o">=</span> <span class="n">signal</span><span class="o">.</span><span class="n">lfilter</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">coeffs</span><span class="p">)</span> | |||
|
156 | ||||
|
157 | <span class="n">x_int</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">response</span> <span class="o">*</span> <span class="n">dy</span> <span class="o">/</span> <span class="n">dist</span> | |||
|
158 | <span class="n">y_int</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">response</span> <span class="o">*</span> <span class="n">dx</span> <span class="o">/</span> <span class="n">dist</span> | |||
|
159 | ||||
|
160 | <span class="c"># un-scale data</span> | |||
|
161 | <span class="n">x_int</span> <span class="o">=</span> <span class="n">x_int</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">xlim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | |||
|
162 | <span class="n">y_int</span> <span class="o">=</span> <span class="n">y_int</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">ylim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | |||
|
163 | ||||
|
164 | <span class="k">return</span> <span class="n">x_int</span><span class="p">,</span> <span class="n">y_int</span> | |||
|
165 | ||||
|
166 | ||||
|
167 | <span class="k">def</span> <span class="nf">XKCDify</span><span class="p">(</span><span class="n">ax</span><span class="p">,</span> <span class="n">mag</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> | |||
|
168 | <span class="n">f1</span><span class="o">=</span><span class="mi">50</span><span class="p">,</span> <span class="n">f2</span><span class="o">=</span><span class="mf">0.01</span><span class="p">,</span> <span class="n">f3</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span> | |||
|
169 | <span class="n">bgcolor</span><span class="o">=</span><span class="s">'w'</span><span class="p">,</span> | |||
|
170 | <span class="n">xaxis_loc</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> | |||
|
171 | <span class="n">yaxis_loc</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> | |||
|
172 | <span class="n">xaxis_arrow</span><span class="o">=</span><span class="s">'+'</span><span class="p">,</span> | |||
|
173 | <span class="n">yaxis_arrow</span><span class="o">=</span><span class="s">'+'</span><span class="p">,</span> | |||
|
174 | <span class="n">ax_extend</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> | |||
|
175 | <span class="n">expand_axes</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span> | |||
|
176 | <span class="sd">"""Make axis look hand-drawn</span> | |||
|
177 | ||||
|
178 | <span class="sd"> This adjusts all lines, text, legends, and axes in the figure to look</span> | |||
|
179 | <span class="sd"> like xkcd plots. Other plot elements are not modified.</span> | |||
|
180 | <span class="sd"> </span> | |||
|
181 | <span class="sd"> Parameters</span> | |||
|
182 | <span class="sd"> ----------</span> | |||
|
183 | <span class="sd"> ax : Axes instance</span> | |||
|
184 | <span class="sd"> the axes to be modified.</span> | |||
|
185 | <span class="sd"> mag : float</span> | |||
|
186 | <span class="sd"> the magnitude of the distortion</span> | |||
|
187 | <span class="sd"> f1, f2, f3 : int, float, int</span> | |||
|
188 | <span class="sd"> filtering parameters. f1 gives the size of the window, f2 gives</span> | |||
|
189 | <span class="sd"> the high-frequency cutoff, f3 gives the size of the filter</span> | |||
|
190 | <span class="sd"> xaxis_loc, yaxis_log : float</span> | |||
|
191 | <span class="sd"> The locations to draw the x and y axes. If not specified, they</span> | |||
|
192 | <span class="sd"> will be drawn from the bottom left of the plot</span> | |||
|
193 | <span class="sd"> xaxis_arrow, yaxis_arrow : str</span> | |||
|
194 | <span class="sd"> where to draw arrows on the x/y axes. Options are '+', '-', '+-', or ''</span> | |||
|
195 | <span class="sd"> ax_extend : float</span> | |||
|
196 | <span class="sd"> How far (fractionally) to extend the drawn axes beyond the original</span> | |||
|
197 | <span class="sd"> axes limits</span> | |||
|
198 | <span class="sd"> expand_axes : bool</span> | |||
|
199 | <span class="sd"> if True, then expand axes to fill the figure (useful if there is only</span> | |||
|
200 | <span class="sd"> a single axes in the figure)</span> | |||
|
201 | <span class="sd"> """</span> | |||
|
202 | <span class="c"># Get axes aspect</span> | |||
|
203 | <span class="n">ext</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">get_window_extent</span><span class="p">()</span><span class="o">.</span><span class="n">extents</span> | |||
|
204 | <span class="n">aspect</span> <span class="o">=</span> <span class="p">(</span><span class="n">ext</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">-</span> <span class="n">ext</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">/</span> <span class="p">(</span><span class="n">ext</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">ext</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> | |||
|
205 | ||||
|
206 | <span class="n">xlim</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">get_xlim</span><span class="p">()</span> | |||
|
207 | <span class="n">ylim</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">get_ylim</span><span class="p">()</span> | |||
|
208 | ||||
|
209 | <span class="n">xspan</span> <span class="o">=</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | |||
|
210 | <span class="n">yspan</span> <span class="o">=</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | |||
|
211 | ||||
|
212 | <span class="n">xax_lim</span> <span class="o">=</span> <span class="p">(</span><span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">ax_extend</span> <span class="o">*</span> <span class="n">xspan</span><span class="p">,</span> | |||
|
213 | <span class="n">xlim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">ax_extend</span> <span class="o">*</span> <span class="n">xspan</span><span class="p">)</span> | |||
|
214 | <span class="n">yax_lim</span> <span class="o">=</span> <span class="p">(</span><span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">ax_extend</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> | |||
|
215 | <span class="n">ylim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">ax_extend</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">)</span> | |||
|
216 | ||||
|
217 | <span class="k">if</span> <span class="n">xaxis_loc</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> | |||
|
218 | <span class="n">xaxis_loc</span> <span class="o">=</span> <span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | |||
|
219 | ||||
|
220 | <span class="k">if</span> <span class="n">yaxis_loc</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> | |||
|
221 | <span class="n">yaxis_loc</span> <span class="o">=</span> <span class="n">xlim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | |||
|
222 | ||||
|
223 | <span class="c"># Draw axes</span> | |||
|
224 | <span class="n">xaxis</span> <span class="o">=</span> <span class="n">pl</span><span class="o">.</span><span class="n">Line2D</span><span class="p">([</span><span class="n">xax_lim</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">xax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">]],</span> <span class="p">[</span><span class="n">xaxis_loc</span><span class="p">,</span> <span class="n">xaxis_loc</span><span class="p">],</span> | |||
|
225 | <span class="n">linestyle</span><span class="o">=</span><span class="s">'-'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'k'</span><span class="p">)</span> | |||
|
226 | <span class="n">yaxis</span> <span class="o">=</span> <span class="n">pl</span><span class="o">.</span><span class="n">Line2D</span><span class="p">([</span><span class="n">yaxis_loc</span><span class="p">,</span> <span class="n">yaxis_loc</span><span class="p">],</span> <span class="p">[</span><span class="n">yax_lim</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">yax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">]],</span> | |||
|
227 | <span class="n">linestyle</span><span class="o">=</span><span class="s">'-'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'k'</span><span class="p">)</span> | |||
|
228 | ||||
|
229 | <span class="c"># Label axes3, 0.5, 'hello', fontsize=14)</span> | |||
|
230 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">xax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">xaxis_loc</span> <span class="o">-</span> <span class="mf">0.02</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> <span class="n">ax</span><span class="o">.</span><span class="n">get_xlabel</span><span class="p">(),</span> | |||
|
231 | <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'top'</span><span class="p">,</span> <span class="n">rotation</span><span class="o">=</span><span class="mi">12</span><span class="p">)</span> | |||
|
232 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">yaxis_loc</span> <span class="o">-</span> <span class="mf">0.02</span> <span class="o">*</span> <span class="n">xspan</span><span class="p">,</span> <span class="n">yax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">ax</span><span class="o">.</span><span class="n">get_ylabel</span><span class="p">(),</span> | |||
|
233 | <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'top'</span><span class="p">,</span> <span class="n">rotation</span><span class="o">=</span><span class="mi">78</span><span class="p">)</span> | |||
|
234 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">''</span><span class="p">)</span> | |||
|
235 | <span class="n">ax</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">''</span><span class="p">)</span> | |||
|
236 | ||||
|
237 | <span class="c"># Add title</span> | |||
|
238 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.5</span> <span class="o">*</span> <span class="p">(</span><span class="n">xax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">xax_lim</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="n">yax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> | |||
|
239 | <span class="n">ax</span><span class="o">.</span><span class="n">get_title</span><span class="p">(),</span> | |||
|
240 | <span class="n">ha</span><span class="o">=</span><span class="s">'center'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">16</span><span class="p">)</span> | |||
|
241 | <span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">''</span><span class="p">)</span> | |||
|
242 | ||||
|
243 | <span class="n">Nlines</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">ax</span><span class="o">.</span><span class="n">lines</span><span class="p">)</span> | |||
|
244 | <span class="n">lines</span> <span class="o">=</span> <span class="p">[</span><span class="n">xaxis</span><span class="p">,</span> <span class="n">yaxis</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="n">ax</span><span class="o">.</span><span class="n">lines</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">Nlines</span><span class="p">)]</span> | |||
|
245 | ||||
|
246 | <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span> | |||
|
247 | <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">get_data</span><span class="p">()</span> | |||
|
248 | ||||
|
249 | <span class="n">x_int</span><span class="p">,</span> <span class="n">y_int</span> <span class="o">=</span> <span class="n">xkcd_line</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">xlim</span><span class="p">,</span> <span class="n">ylim</span><span class="p">,</span> | |||
|
250 | <span class="n">mag</span><span class="p">,</span> <span class="n">f1</span><span class="p">,</span> <span class="n">f2</span><span class="p">,</span> <span class="n">f3</span><span class="p">)</span> | |||
|
251 | ||||
|
252 | <span class="c"># create foreground and background line</span> | |||
|
253 | <span class="n">lw</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">get_linewidth</span><span class="p">()</span> | |||
|
254 | <span class="n">line</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">lw</span><span class="p">)</span> | |||
|
255 | <span class="n">line</span><span class="o">.</span><span class="n">set_data</span><span class="p">(</span><span class="n">x_int</span><span class="p">,</span> <span class="n">y_int</span><span class="p">)</span> | |||
|
256 | ||||
|
257 | <span class="c"># don't add background line for axes</span> | |||
|
258 | <span class="k">if</span> <span class="p">(</span><span class="n">line</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">xaxis</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="n">line</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">yaxis</span><span class="p">):</span> | |||
|
259 | <span class="n">line_bg</span> <span class="o">=</span> <span class="n">pl</span><span class="o">.</span><span class="n">Line2D</span><span class="p">(</span><span class="n">x_int</span><span class="p">,</span> <span class="n">y_int</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="n">bgcolor</span><span class="p">,</span> | |||
|
260 | <span class="n">linewidth</span><span class="o">=</span><span class="mi">8</span> <span class="o">*</span> <span class="n">lw</span><span class="p">)</span> | |||
|
261 | ||||
|
262 | <span class="n">ax</span><span class="o">.</span><span class="n">add_line</span><span class="p">(</span><span class="n">line_bg</span><span class="p">)</span> | |||
|
263 | <span class="n">ax</span><span class="o">.</span><span class="n">add_line</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> | |||
|
264 | ||||
|
265 | <span class="c"># Draw arrow-heads at the end of axes lines</span> | |||
|
266 | <span class="n">arr1</span> <span class="o">=</span> <span class="mf">0.03</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">])</span> | |||
|
267 | <span class="n">arr2</span> <span class="o">=</span> <span class="mf">0.02</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> | |||
|
268 | ||||
|
269 | <span class="n">arr1</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">normal</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.005</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> | |||
|
270 | <span class="n">arr2</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">normal</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.005</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> | |||
|
271 | ||||
|
272 | <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">xaxis</span><span class="o">.</span><span class="n">get_data</span><span class="p">()</span> | |||
|
273 | <span class="k">if</span> <span class="s">'+'</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">xaxis_arrow</span><span class="p">):</span> | |||
|
274 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">arr1</span> <span class="o">*</span> <span class="n">xspan</span> <span class="o">*</span> <span class="n">aspect</span><span class="p">,</span> | |||
|
275 | <span class="n">y</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">arr2</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> | |||
|
276 | <span class="n">color</span><span class="o">=</span><span class="s">'k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> | |||
|
277 | <span class="k">if</span> <span class="s">'-'</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">xaxis_arrow</span><span class="p">):</span> | |||
|
278 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">arr1</span> <span class="o">*</span> <span class="n">xspan</span> <span class="o">*</span> <span class="n">aspect</span><span class="p">,</span> | |||
|
279 | <span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">arr2</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> | |||
|
280 | <span class="n">color</span><span class="o">=</span><span class="s">'k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> | |||
|
281 | ||||
|
282 | <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">yaxis</span><span class="o">.</span><span class="n">get_data</span><span class="p">()</span> | |||
|
283 | <span class="k">if</span> <span class="s">'+'</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">yaxis_arrow</span><span class="p">):</span> | |||
|
284 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">arr2</span> <span class="o">*</span> <span class="n">xspan</span> <span class="o">*</span> <span class="n">aspect</span><span class="p">,</span> | |||
|
285 | <span class="n">y</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">arr1</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> | |||
|
286 | <span class="n">color</span><span class="o">=</span><span class="s">'k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> | |||
|
287 | <span class="k">if</span> <span class="s">'-'</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">yaxis_arrow</span><span class="p">):</span> | |||
|
288 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">arr2</span> <span class="o">*</span> <span class="n">xspan</span> <span class="o">*</span> <span class="n">aspect</span><span class="p">,</span> | |||
|
289 | <span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">arr1</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> | |||
|
290 | <span class="n">color</span><span class="o">=</span><span class="s">'k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> | |||
|
291 | ||||
|
292 | <span class="c"># Change all the fonts to humor-sans.</span> | |||
|
293 | <span class="n">prop</span> <span class="o">=</span> <span class="n">fm</span><span class="o">.</span><span class="n">FontProperties</span><span class="p">(</span><span class="n">fname</span><span class="o">=</span><span class="s">'Humor-Sans.ttf'</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">16</span><span class="p">)</span> | |||
|
294 | <span class="k">for</span> <span class="n">text</span> <span class="ow">in</span> <span class="n">ax</span><span class="o">.</span><span class="n">texts</span><span class="p">:</span> | |||
|
295 | <span class="n">text</span><span class="o">.</span><span class="n">set_fontproperties</span><span class="p">(</span><span class="n">prop</span><span class="p">)</span> | |||
|
296 | ||||
|
297 | <span class="c"># modify legend</span> | |||
|
298 | <span class="n">leg</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">get_legend</span><span class="p">()</span> | |||
|
299 | <span class="k">if</span> <span class="n">leg</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span> | |||
|
300 | <span class="n">leg</span><span class="o">.</span><span class="n">set_frame_on</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span> | |||
|
301 | ||||
|
302 | <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">leg</span><span class="o">.</span><span class="n">get_children</span><span class="p">():</span> | |||
|
303 | <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">pl</span><span class="o">.</span><span class="n">Line2D</span><span class="p">):</span> | |||
|
304 | <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="n">get_data</span><span class="p">()</span> | |||
|
305 | <span class="n">child</span><span class="o">.</span><span class="n">set_data</span><span class="p">(</span><span class="n">xkcd_line</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">mag</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">f1</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span> <span class="n">f2</span><span class="o">=</span><span class="mf">0.001</span><span class="p">))</span> | |||
|
306 | <span class="n">child</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">child</span><span class="o">.</span><span class="n">get_linewidth</span><span class="p">())</span> | |||
|
307 | <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">pl</span><span class="o">.</span><span class="n">Text</span><span class="p">):</span> | |||
|
308 | <span class="n">child</span><span class="o">.</span><span class="n">set_fontproperties</span><span class="p">(</span><span class="n">prop</span><span class="p">)</span> | |||
|
309 | ||||
|
310 | <span class="c"># Set the axis limits</span> | |||
|
311 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="n">xax_lim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mf">0.1</span> <span class="o">*</span> <span class="n">xspan</span><span class="p">,</span> | |||
|
312 | <span class="n">xax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.1</span> <span class="o">*</span> <span class="n">xspan</span><span class="p">)</span> | |||
|
313 | <span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="n">yax_lim</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mf">0.1</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">,</span> | |||
|
314 | <span class="n">yax_lim</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.1</span> <span class="o">*</span> <span class="n">yspan</span><span class="p">)</span> | |||
|
315 | ||||
|
316 | <span class="c"># adjust the axes</span> | |||
|
317 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">([])</span> | |||
|
318 | <span class="n">ax</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">([])</span> | |||
|
319 | ||||
|
320 | <span class="k">if</span> <span class="n">expand_axes</span><span class="p">:</span> | |||
|
321 | <span class="n">ax</span><span class="o">.</span><span class="n">figure</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="n">bgcolor</span><span class="p">)</span> | |||
|
322 | <span class="n">ax</span><span class="o">.</span><span class="n">set_axis_off</span><span class="p">()</span> | |||
|
323 | <span class="n">ax</span><span class="o">.</span><span class="n">set_position</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> | |||
|
324 | ||||
|
325 | <span class="k">return</span> <span class="n">ax</span> | |||
|
326 | </pre></div> | |||
|
327 | ||||
|
328 | ||||
|
329 | ||||
|
330 | ## Testing it Out | |||
|
331 | ||||
|
332 | Let's test this out with a simple plot. We'll plot two curves, add some labels, | |||
|
333 | and then call ``XKCDify`` on the axis. I think the results are pretty nice! | |||
|
334 | ||||
|
335 | <div class="highlight"><pre><span class="o">%</span><span class="k">pylab</span> <span class="n">inline</span> | |||
|
336 | </pre></div> | |||
|
337 | ||||
|
338 | ||||
|
339 | ||||
|
340 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
341 | For more information, type 'help(pylab)'. | |||
|
342 | ||||
|
343 | ||||
|
344 | <div class="highlight"><pre><span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> | |||
|
345 | ||||
|
346 | <span class="n">ax</span> <span class="o">=</span> <span class="n">pylab</span><span class="o">.</span><span class="n">axes</span><span class="p">()</span> | |||
|
347 | ||||
|
348 | <span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span> | |||
|
349 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="mf">0.1</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="mi">5</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span><span class="p">),</span> <span class="s">'b'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'damped sine'</span><span class="p">)</span> | |||
|
350 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="mf">0.1</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="mi">5</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span><span class="p">),</span> <span class="s">'r'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'damped cosine'</span><span class="p">)</span> | |||
|
351 | ||||
|
352 | <span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'check it out!'</span><span class="p">)</span> | |||
|
353 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'x label'</span><span class="p">)</span> | |||
|
354 | <span class="n">ax</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'y label'</span><span class="p">)</span> | |||
|
355 | ||||
|
356 | <span class="n">ax</span><span class="o">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s">'lower right'</span><span class="p">)</span> | |||
|
357 | ||||
|
358 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> | |||
|
359 | <span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="o">-</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">)</span> | |||
|
360 | ||||
|
361 | <span class="c">#XKCDify the axes -- this operates in-place</span> | |||
|
362 | <span class="n">XKCDify</span><span class="p">(</span><span class="n">ax</span><span class="p">,</span> <span class="n">xaxis_loc</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span> <span class="n">yaxis_loc</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> | |||
|
363 | <span class="n">xaxis_arrow</span><span class="o">=</span><span class="s">'+-'</span><span class="p">,</span> <span class="n">yaxis_arrow</span><span class="o">=</span><span class="s">'+-'</span><span class="p">,</span> | |||
|
364 | <span class="n">expand_axes</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> | |||
|
365 | </pre></div> | |||
|
366 | ||||
|
367 | ||||
|
368 | <pre> | |||
|
369 | <matplotlib.axes.AxesSubplot at 0x2fecbd0> | |||
|
370 | </pre> | |||
|
371 | ||||
|
372 | ||||
|
373 | ![](tests/ipynbref/XKCD_plots_orig_files/XKCD_plots_orig_fig_00.png) | |||
|
374 | ||||
|
375 | ||||
|
376 | ## Duplicating an XKCD Comic | |||
|
377 | ||||
|
378 | Now let's see if we can use this to replicated an XKCD comic in matplotlib. | |||
|
379 | This is a good one: | |||
|
380 | ||||
|
381 | <div class="highlight"><pre><span class="n">Image</span><span class="p">(</span><span class="s">'http://imgs.xkcd.com/comics/front_door.png'</span><span class="p">)</span> | |||
|
382 | </pre></div> | |||
|
383 | ||||
|
384 | ||||
|
385 | <pre> | |||
|
386 | <IPython.core.display.Image at 0x2ff4a10> | |||
|
387 | </pre> | |||
|
388 | ||||
|
389 | ||||
|
390 | With the new ``XKCDify`` function, this is relatively easy to replicate. The results | |||
|
391 | are not exactly identical, but I think it definitely gets the point across! | |||
|
392 | ||||
|
393 | <div class="highlight"><pre><span class="c"># Some helper functions</span> | |||
|
394 | <span class="k">def</span> <span class="nf">norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">x0</span><span class="p">,</span> <span class="n">sigma</span><span class="p">):</span> | |||
|
395 | <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="mf">0.5</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">x0</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">/</span> <span class="n">sigma</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> | |||
|
396 | ||||
|
397 | <span class="k">def</span> <span class="nf">sigmoid</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">x0</span><span class="p">,</span> <span class="n">alpha</span><span class="p">):</span> | |||
|
398 | <span class="k">return</span> <span class="mf">1.</span> <span class="o">/</span> <span class="p">(</span><span class="mf">1.</span> <span class="o">+</span> <span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">x0</span><span class="p">)</span> <span class="o">/</span> <span class="n">alpha</span><span class="p">))</span> | |||
|
399 | ||||
|
400 | <span class="c"># define the curves</span> | |||
|
401 | <span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span> | |||
|
402 | <span class="n">y1</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">))</span> <span class="o">+</span> <span class="mf">0.2</span> <span class="o">*</span> <span class="p">(</span><span class="mf">1.5</span> <span class="o">-</span> <span class="n">sigmoid</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">))</span> | |||
|
403 | ||||
|
404 | <span class="n">y2</span> <span class="o">=</span> <span class="mf">0.2</span> <span class="o">*</span> <span class="n">norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">)</span> <span class="o">+</span> <span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.6</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">))</span> <span class="o">+</span> <span class="mf">0.1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">sigmoid</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.75</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">))</span> | |||
|
405 | ||||
|
406 | <span class="n">y3</span> <span class="o">=</span> <span class="mf">0.05</span> <span class="o">+</span> <span class="mf">1.4</span> <span class="o">*</span> <span class="n">norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.85</span><span class="p">,</span> <span class="mf">0.08</span><span class="p">)</span> | |||
|
407 | <span class="n">y3</span><span class="p">[</span><span class="n">x</span> <span class="o">></span> <span class="mf">0.85</span><span class="p">]</span> <span class="o">=</span> <span class="mf">0.05</span> <span class="o">+</span> <span class="mf">1.4</span> <span class="o">*</span> <span class="n">norm</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="n">x</span> <span class="o">></span> <span class="mf">0.85</span><span class="p">],</span> <span class="mf">0.85</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">)</span> | |||
|
408 | ||||
|
409 | <span class="c"># draw the curves</span> | |||
|
410 | <span class="n">ax</span> <span class="o">=</span> <span class="n">pl</span><span class="o">.</span><span class="n">axes</span><span class="p">()</span> | |||
|
411 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s">'gray'</span><span class="p">)</span> | |||
|
412 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y2</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s">'blue'</span><span class="p">)</span> | |||
|
413 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y3</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s">'red'</span><span class="p">)</span> | |||
|
414 | ||||
|
415 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="s">"Yard"</span><span class="p">)</span> | |||
|
416 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="s">"Steps"</span><span class="p">)</span> | |||
|
417 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.7</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="s">"Door"</span><span class="p">)</span> | |||
|
418 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.9</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="s">"Inside"</span><span class="p">)</span> | |||
|
419 | ||||
|
420 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.05</span><span class="p">,</span> <span class="mf">1.1</span><span class="p">,</span> <span class="s">"fear that</span><span class="se">\n</span><span class="s">there's</span><span class="se">\n</span><span class="s">something</span><span class="se">\n</span><span class="s">behind me"</span><span class="p">)</span> | |||
|
421 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">0.15</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">],</span> <span class="s">'-k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span> | |||
|
422 | ||||
|
423 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.25</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="s">"forward</span><span class="se">\n</span><span class="s">speed"</span><span class="p">)</span> | |||
|
424 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">0.32</span><span class="p">,</span> <span class="mf">0.35</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.75</span><span class="p">,</span> <span class="mf">0.35</span><span class="p">],</span> <span class="s">'-k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span> | |||
|
425 | ||||
|
426 | <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.9</span><span class="p">,</span> <span class="mf">0.4</span><span class="p">,</span> <span class="s">"embarrassment"</span><span class="p">)</span> | |||
|
427 | <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.55</span><span class="p">,</span> <span class="mf">1.05</span><span class="p">],</span> <span class="s">'-k'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span> | |||
|
428 | ||||
|
429 | <span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">"Walking back to my</span><span class="se">\n</span><span class="s">front door at night:"</span><span class="p">)</span> | |||
|
430 | ||||
|
431 | <span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> | |||
|
432 | <span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">)</span> | |||
|
433 | ||||
|
434 | <span class="c"># modify all the axes elements in-place</span> | |||
|
435 | <span class="n">XKCDify</span><span class="p">(</span><span class="n">ax</span><span class="p">,</span> <span class="n">expand_axes</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> | |||
|
436 | </pre></div> | |||
|
437 | ||||
|
438 | ||||
|
439 | <pre> | |||
|
440 | <matplotlib.axes.AxesSubplot at 0x2fef210> | |||
|
441 | </pre> | |||
|
442 | ||||
|
443 | ||||
|
444 | ![](tests/ipynbref/XKCD_plots_orig_files/XKCD_plots_orig_fig_01.png) | |||
|
445 | ||||
|
446 | ||||
|
447 | Pretty good for a couple hours's work! | |||
|
448 | ||||
|
449 | I think the possibilities here are pretty limitless: this is going to be a hugely | |||
|
450 | useful and popular feature in matplotlib, especially when the sketch artist PR is mature | |||
|
451 | and part of the main package. I imagine using this style of plot for schematic figures | |||
|
452 | in presentations where the normal crisp matplotlib lines look a bit too "scientific". | |||
|
453 | I'm giving a few talks at the end of the month... maybe I'll even use some of | |||
|
454 | this code there. | |||
|
455 | ||||
|
456 | This post was written entirely in an IPython Notebook: the notebook file is available for | |||
|
457 | download [here](http://jakevdp.github.com/downloads/notebooks/XKCD_plots.ipynb). | |||
|
458 | For more information on blogging with notebooks in octopress, see my | |||
|
459 | [previous post](http://jakevdp.github.com/blog/2012/10/04/blogging-with-ipython/) | |||
|
460 | on the subject. |
This diff has been collapsed as it changes many lines, (626 lines changed) Show them Hide them | |||||
@@ -0,0 +1,626 b'' | |||||
|
1 | %% This file was auto-generated by IPython. | |||
|
2 | %% Conversion from the original notebook file: | |||
|
3 | %% tests/ipynbref/XKCD_plots.orig.ipynb | |||
|
4 | %% | |||
|
5 | \documentclass[11pt,english]{article} | |||
|
6 | ||||
|
7 | %% This is the automatic preamble used by IPython. Note that it does *not* | |||
|
8 | %% include a documentclass declaration, that is added at runtime to the overall | |||
|
9 | %% document. | |||
|
10 | ||||
|
11 | \usepackage{amsmath} | |||
|
12 | \usepackage{amssymb} | |||
|
13 | \usepackage{graphicx} | |||
|
14 | \usepackage{ucs} | |||
|
15 | \usepackage[utf8x]{inputenc} | |||
|
16 | ||||
|
17 | % needed for markdown enumerations to work | |||
|
18 | \usepackage{enumerate} | |||
|
19 | ||||
|
20 | % Slightly bigger margins than the latex defaults | |||
|
21 | \usepackage{geometry} | |||
|
22 | \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm} | |||
|
23 | ||||
|
24 | % Define a few colors for use in code, links and cell shading | |||
|
25 | \usepackage{color} | |||
|
26 | \definecolor{orange}{cmyk}{0,0.4,0.8,0.2} | |||
|
27 | \definecolor{darkorange}{rgb}{.71,0.21,0.01} | |||
|
28 | \definecolor{darkgreen}{rgb}{.12,.54,.11} | |||
|
29 | \definecolor{myteal}{rgb}{.26, .44, .56} | |||
|
30 | \definecolor{gray}{gray}{0.45} | |||
|
31 | \definecolor{lightgray}{gray}{.95} | |||
|
32 | \definecolor{mediumgray}{gray}{.8} | |||
|
33 | \definecolor{inputbackground}{rgb}{.95, .95, .85} | |||
|
34 | \definecolor{outputbackground}{rgb}{.95, .95, .95} | |||
|
35 | \definecolor{traceback}{rgb}{1, .95, .95} | |||
|
36 | ||||
|
37 | % Framed environments for code cells (inputs, outputs, errors, ...). The | |||
|
38 | % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't | |||
|
39 | % randomly change them unless you're sure of the effect it will have. | |||
|
40 | \usepackage{framed} | |||
|
41 | ||||
|
42 | % remove extraneous vertical space in boxes | |||
|
43 | \setlength\fboxsep{0pt} | |||
|
44 | ||||
|
45 | % codecell is the whole input+output set of blocks that a Code cell can | |||
|
46 | % generate. | |||
|
47 | ||||
|
48 | % TODO: unfortunately, it seems that using a framed codecell environment breaks | |||
|
49 | % the ability of the frames inside of it to be broken across pages. This | |||
|
50 | % causes at least the problem of having lots of empty space at the bottom of | |||
|
51 | % pages as new frames are moved to the next page, and if a single frame is too | |||
|
52 | % long to fit on a page, will completely stop latex from compiling the | |||
|
53 | % document. So unless we figure out a solution to this, we'll have to instead | |||
|
54 | % leave the codecell env. as empty. I'm keeping the original codecell | |||
|
55 | % definition here (a thin vertical bar) for reference, in case we find a | |||
|
56 | % solution to the page break issue. | |||
|
57 | ||||
|
58 | %% \newenvironment{codecell}{% | |||
|
59 | %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}% | |||
|
60 | %% \MakeFramed{\vspace{-0.5em}}} | |||
|
61 | %% {\unskip\endMakeFramed} | |||
|
62 | ||||
|
63 | % For now, make this a no-op... | |||
|
64 | \newenvironment{codecell}{} | |||
|
65 | ||||
|
66 | \newenvironment{codeinput}{% | |||
|
67 | \def\FrameCommand{\colorbox{inputbackground}}% | |||
|
68 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
69 | {\unskip\endMakeFramed} | |||
|
70 | ||||
|
71 | \newenvironment{codeoutput}{% | |||
|
72 | \def\FrameCommand{\colorbox{outputbackground}}% | |||
|
73 | \vspace{-1.4em} | |||
|
74 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
75 | {\unskip\medskip\endMakeFramed} | |||
|
76 | ||||
|
77 | \newenvironment{traceback}{% | |||
|
78 | \def\FrameCommand{\colorbox{traceback}}% | |||
|
79 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
80 | {\endMakeFramed} | |||
|
81 | ||||
|
82 | % Use and configure listings package for nicely formatted code | |||
|
83 | \usepackage{listingsutf8} | |||
|
84 | \lstset{ | |||
|
85 | language=python, | |||
|
86 | inputencoding=utf8x, | |||
|
87 | extendedchars=\true, | |||
|
88 | aboveskip=\smallskipamount, | |||
|
89 | belowskip=\smallskipamount, | |||
|
90 | xleftmargin=2mm, | |||
|
91 | breaklines=true, | |||
|
92 | basicstyle=\small \ttfamily, | |||
|
93 | showstringspaces=false, | |||
|
94 | keywordstyle=\color{blue}\bfseries, | |||
|
95 | commentstyle=\color{myteal}, | |||
|
96 | stringstyle=\color{darkgreen}, | |||
|
97 | identifierstyle=\color{darkorange}, | |||
|
98 | columns=fullflexible, % tighter character kerning, like verb | |||
|
99 | } | |||
|
100 | ||||
|
101 | % The hyperref package gives us a pdf with properly built | |||
|
102 | % internal navigation ('pdf bookmarks' for the table of contents, | |||
|
103 | % internal cross-reference links, web links for URLs, etc.) | |||
|
104 | \usepackage{hyperref} | |||
|
105 | \hypersetup{ | |||
|
106 | breaklinks=true, % so long urls are correctly broken across lines | |||
|
107 | colorlinks=true, | |||
|
108 | urlcolor=blue, | |||
|
109 | linkcolor=darkorange, | |||
|
110 | citecolor=darkgreen, | |||
|
111 | } | |||
|
112 | ||||
|
113 | % hardcode size of all verbatim environments to be a bit smaller | |||
|
114 | \makeatletter | |||
|
115 | \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt | |||
|
116 | \makeatother | |||
|
117 | ||||
|
118 | % Prevent overflowing lines due to urls and other hard-to-break entities. | |||
|
119 | \sloppy | |||
|
120 | ||||
|
121 | \begin{document} | |||
|
122 | ||||
|
123 | \section{XKCD plots in Matplotlib} | |||
|
124 | This notebook originally appeared as a blog post at | |||
|
125 | \href{http://jakevdp.github.com/blog/2012/10/07/xkcd-style-plots-in-matplotlib/}{Pythonic | |||
|
126 | Perambulations} by Jake Vanderplas. | |||
|
127 | ||||
|
128 | One of the problems I've had with typical matplotlib figures is that | |||
|
129 | everything in them is so precise, so perfect. For an example of what I | |||
|
130 | mean, take a look at this figure: | |||
|
131 | ||||
|
132 | \begin{codecell} | |||
|
133 | \begin{codeinput} | |||
|
134 | \begin{lstlisting} | |||
|
135 | from IPython.display import Image | |||
|
136 | Image('http://jakevdp.github.com/figures/xkcd_version.png') | |||
|
137 | \end{lstlisting} | |||
|
138 | \end{codeinput} | |||
|
139 | \begin{codeoutput} | |||
|
140 | \begin{verbatim} | |||
|
141 | <IPython.core.display.Image at 0x2fef710> | |||
|
142 | \end{verbatim} | |||
|
143 | \end{codeoutput} | |||
|
144 | \end{codecell} | |||
|
145 | Sometimes when showing schematic plots, this is the type of figure I | |||
|
146 | want to display. But drawing it by hand is a pain: I'd rather just use | |||
|
147 | matplotlib. The problem is, matplotlib is a bit too precise. Attempting | |||
|
148 | to duplicate this figure in matplotlib leads to something like this: | |||
|
149 | ||||
|
150 | \begin{codecell} | |||
|
151 | \begin{codeinput} | |||
|
152 | \begin{lstlisting} | |||
|
153 | Image('http://jakevdp.github.com/figures/mpl_version.png') | |||
|
154 | \end{lstlisting} | |||
|
155 | \end{codeinput} | |||
|
156 | \begin{codeoutput} | |||
|
157 | \begin{verbatim} | |||
|
158 | <IPython.core.display.Image at 0x2fef0d0> | |||
|
159 | \end{verbatim} | |||
|
160 | \end{codeoutput} | |||
|
161 | \end{codecell} | |||
|
162 | It just doesn't have the same effect. Matplotlib is great for scientific | |||
|
163 | plots, but sometimes you don't want to be so precise. | |||
|
164 | ||||
|
165 | This subject has recently come up on the matplotlib mailing list, and | |||
|
166 | started some interesting discussions. As near as I can tell, this | |||
|
167 | started with a thread on a | |||
|
168 | \href{http://mathematica.stackexchange.com/questions/11350/xkcd-style-graphs}{mathematica | |||
|
169 | list} which prompted a thread on the | |||
|
170 | \href{http://matplotlib.1069221.n5.nabble.com/XKCD-style-graphs-td39226.html}{matplotlib | |||
|
171 | list} wondering if the same could be done in matplotlib. | |||
|
172 | ||||
|
173 | Damon McDougall offered a quick | |||
|
174 | \href{http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg25499.html}{solution} | |||
|
175 | which was improved by Fernando Perez in | |||
|
176 | \href{http://nbviewer.ipython.org/3835181/}{this notebook}, and within a | |||
|
177 | few days there was a | |||
|
178 | \href{https://github.com/matplotlib/matplotlib/pull/1329}{matplotlib | |||
|
179 | pull request} offering a very general way to create sketch-style plots | |||
|
180 | in matplotlib. Only a few days from a cool idea to a working | |||
|
181 | implementation: this is one of the most incredible aspects of package | |||
|
182 | development on github. | |||
|
183 | ||||
|
184 | The pull request looks really nice, but will likely not be included in a | |||
|
185 | released version of matplotlib until at least version 1.3. In the | |||
|
186 | mean-time, I wanted a way to play around with these types of plots in a | |||
|
187 | way that is compatible with the current release of matplotlib. To do | |||
|
188 | that, I created the following code: | |||
|
189 | ||||
|
190 | \subsection{The Code: XKCDify} | |||
|
191 | XKCDify will take a matplotlib \texttt{Axes} instance, and modify the | |||
|
192 | plot elements in-place to make them look hand-drawn. First off, we'll | |||
|
193 | need to make sure we have the Humor Sans font. It can be downloaded | |||
|
194 | using the command below. | |||
|
195 | ||||
|
196 | Next we'll create a function \texttt{xkcd\_line} to add jitter to lines. | |||
|
197 | We want this to be very general, so we'll normalize the size of the | |||
|
198 | lines, and use a low-pass filter to add correlated noise, perpendicular | |||
|
199 | to the direction of the line. There are a few parameters for this filter | |||
|
200 | that can be tweaked to customize the appearance of the jitter. | |||
|
201 | ||||
|
202 | Finally, we'll create a function which accepts a matplotlib axis, and | |||
|
203 | calls \texttt{xkcd\_line} on all lines in the axis. Additionally, we'll | |||
|
204 | switch the font of all text in the axes, and add some background lines | |||
|
205 | for a nice effect where lines cross. We'll also draw axes, and move the | |||
|
206 | axes labels and titles to the appropriate location. | |||
|
207 | ||||
|
208 | \begin{codecell} | |||
|
209 | \begin{codeinput} | |||
|
210 | \begin{lstlisting} | |||
|
211 | """ | |||
|
212 | XKCD plot generator | |||
|
213 | ------------------- | |||
|
214 | Author: Jake Vanderplas | |||
|
215 | ||||
|
216 | This is a script that will take any matplotlib line diagram, and convert it | |||
|
217 | to an XKCD-style plot. It will work for plots with line & text elements, | |||
|
218 | including axes labels and titles (but not axes tick labels). | |||
|
219 | ||||
|
220 | The idea for this comes from work by Damon McDougall | |||
|
221 | http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg25499.html | |||
|
222 | """ | |||
|
223 | import numpy as np | |||
|
224 | import pylab as pl | |||
|
225 | from scipy import interpolate, signal | |||
|
226 | import matplotlib.font_manager as fm | |||
|
227 | ||||
|
228 | ||||
|
229 | # We need a special font for the code below. It can be downloaded this way: | |||
|
230 | import os | |||
|
231 | import urllib2 | |||
|
232 | if not os.path.exists('Humor-Sans.ttf'): | |||
|
233 | fhandle = urllib2.urlopen('http://antiyawn.com/uploads/Humor-Sans.ttf') | |||
|
234 | open('Humor-Sans.ttf', 'wb').write(fhandle.read()) | |||
|
235 | ||||
|
236 | ||||
|
237 | def xkcd_line(x, y, xlim=None, ylim=None, | |||
|
238 | mag=1.0, f1=30, f2=0.05, f3=15): | |||
|
239 | """ | |||
|
240 | Mimic a hand-drawn line from (x, y) data | |||
|
241 | ||||
|
242 | Parameters | |||
|
243 | ---------- | |||
|
244 | x, y : array_like | |||
|
245 | arrays to be modified | |||
|
246 | xlim, ylim : data range | |||
|
247 | the assumed plot range for the modification. If not specified, | |||
|
248 | they will be guessed from the data | |||
|
249 | mag : float | |||
|
250 | magnitude of distortions | |||
|
251 | f1, f2, f3 : int, float, int | |||
|
252 | filtering parameters. f1 gives the size of the window, f2 gives | |||
|
253 | the high-frequency cutoff, f3 gives the size of the filter | |||
|
254 | ||||
|
255 | Returns | |||
|
256 | ------- | |||
|
257 | x, y : ndarrays | |||
|
258 | The modified lines | |||
|
259 | """ | |||
|
260 | x = np.asarray(x) | |||
|
261 | y = np.asarray(y) | |||
|
262 | ||||
|
263 | # get limits for rescaling | |||
|
264 | if xlim is None: | |||
|
265 | xlim = (x.min(), x.max()) | |||
|
266 | if ylim is None: | |||
|
267 | ylim = (y.min(), y.max()) | |||
|
268 | ||||
|
269 | if xlim[1] == xlim[0]: | |||
|
270 | xlim = ylim | |||
|
271 | ||||
|
272 | if ylim[1] == ylim[0]: | |||
|
273 | ylim = xlim | |||
|
274 | ||||
|
275 | # scale the data | |||
|
276 | x_scaled = (x - xlim[0]) * 1. / (xlim[1] - xlim[0]) | |||
|
277 | y_scaled = (y - ylim[0]) * 1. / (ylim[1] - ylim[0]) | |||
|
278 | ||||
|
279 | # compute the total distance along the path | |||
|
280 | dx = x_scaled[1:] - x_scaled[:-1] | |||
|
281 | dy = y_scaled[1:] - y_scaled[:-1] | |||
|
282 | dist_tot = np.sum(np.sqrt(dx * dx + dy * dy)) | |||
|
283 | ||||
|
284 | # number of interpolated points is proportional to the distance | |||
|
285 | Nu = int(200 * dist_tot) | |||
|
286 | u = np.arange(-1, Nu + 1) * 1. / (Nu - 1) | |||
|
287 | ||||
|
288 | # interpolate curve at sampled points | |||
|
289 | k = min(3, len(x) - 1) | |||
|
290 | res = interpolate.splprep([x_scaled, y_scaled], s=0, k=k) | |||
|
291 | x_int, y_int = interpolate.splev(u, res[0]) | |||
|
292 | ||||
|
293 | # we'll perturb perpendicular to the drawn line | |||
|
294 | dx = x_int[2:] - x_int[:-2] | |||
|
295 | dy = y_int[2:] - y_int[:-2] | |||
|
296 | dist = np.sqrt(dx * dx + dy * dy) | |||
|
297 | ||||
|
298 | # create a filtered perturbation | |||
|
299 | coeffs = mag * np.random.normal(0, 0.01, len(x_int) - 2) | |||
|
300 | b = signal.firwin(f1, f2 * dist_tot, window=('kaiser', f3)) | |||
|
301 | response = signal.lfilter(b, 1, coeffs) | |||
|
302 | ||||
|
303 | x_int[1:-1] += response * dy / dist | |||
|
304 | y_int[1:-1] += response * dx / dist | |||
|
305 | ||||
|
306 | # un-scale data | |||
|
307 | x_int = x_int[1:-1] * (xlim[1] - xlim[0]) + xlim[0] | |||
|
308 | y_int = y_int[1:-1] * (ylim[1] - ylim[0]) + ylim[0] | |||
|
309 | ||||
|
310 | return x_int, y_int | |||
|
311 | ||||
|
312 | ||||
|
313 | def XKCDify(ax, mag=1.0, | |||
|
314 | f1=50, f2=0.01, f3=15, | |||
|
315 | bgcolor='w', | |||
|
316 | xaxis_loc=None, | |||
|
317 | yaxis_loc=None, | |||
|
318 | xaxis_arrow='+', | |||
|
319 | yaxis_arrow='+', | |||
|
320 | ax_extend=0.1, | |||
|
321 | expand_axes=False): | |||
|
322 | """Make axis look hand-drawn | |||
|
323 | ||||
|
324 | This adjusts all lines, text, legends, and axes in the figure to look | |||
|
325 | like xkcd plots. Other plot elements are not modified. | |||
|
326 | ||||
|
327 | Parameters | |||
|
328 | ---------- | |||
|
329 | ax : Axes instance | |||
|
330 | the axes to be modified. | |||
|
331 | mag : float | |||
|
332 | the magnitude of the distortion | |||
|
333 | f1, f2, f3 : int, float, int | |||
|
334 | filtering parameters. f1 gives the size of the window, f2 gives | |||
|
335 | the high-frequency cutoff, f3 gives the size of the filter | |||
|
336 | xaxis_loc, yaxis_log : float | |||
|
337 | The locations to draw the x and y axes. If not specified, they | |||
|
338 | will be drawn from the bottom left of the plot | |||
|
339 | xaxis_arrow, yaxis_arrow : str | |||
|
340 | where to draw arrows on the x/y axes. Options are '+', '-', '+-', or '' | |||
|
341 | ax_extend : float | |||
|
342 | How far (fractionally) to extend the drawn axes beyond the original | |||
|
343 | axes limits | |||
|
344 | expand_axes : bool | |||
|
345 | if True, then expand axes to fill the figure (useful if there is only | |||
|
346 | a single axes in the figure) | |||
|
347 | """ | |||
|
348 | # Get axes aspect | |||
|
349 | ext = ax.get_window_extent().extents | |||
|
350 | aspect = (ext[3] - ext[1]) / (ext[2] - ext[0]) | |||
|
351 | ||||
|
352 | xlim = ax.get_xlim() | |||
|
353 | ylim = ax.get_ylim() | |||
|
354 | ||||
|
355 | xspan = xlim[1] - xlim[0] | |||
|
356 | yspan = ylim[1] - xlim[0] | |||
|
357 | ||||
|
358 | xax_lim = (xlim[0] - ax_extend * xspan, | |||
|
359 | xlim[1] + ax_extend * xspan) | |||
|
360 | yax_lim = (ylim[0] - ax_extend * yspan, | |||
|
361 | ylim[1] + ax_extend * yspan) | |||
|
362 | ||||
|
363 | if xaxis_loc is None: | |||
|
364 | xaxis_loc = ylim[0] | |||
|
365 | ||||
|
366 | if yaxis_loc is None: | |||
|
367 | yaxis_loc = xlim[0] | |||
|
368 | ||||
|
369 | # Draw axes | |||
|
370 | xaxis = pl.Line2D([xax_lim[0], xax_lim[1]], [xaxis_loc, xaxis_loc], | |||
|
371 | linestyle='-', color='k') | |||
|
372 | yaxis = pl.Line2D([yaxis_loc, yaxis_loc], [yax_lim[0], yax_lim[1]], | |||
|
373 | linestyle='-', color='k') | |||
|
374 | ||||
|
375 | # Label axes3, 0.5, 'hello', fontsize=14) | |||
|
376 | ax.text(xax_lim[1], xaxis_loc - 0.02 * yspan, ax.get_xlabel(), | |||
|
377 | fontsize=14, ha='right', va='top', rotation=12) | |||
|
378 | ax.text(yaxis_loc - 0.02 * xspan, yax_lim[1], ax.get_ylabel(), | |||
|
379 | fontsize=14, ha='right', va='top', rotation=78) | |||
|
380 | ax.set_xlabel('') | |||
|
381 | ax.set_ylabel('') | |||
|
382 | ||||
|
383 | # Add title | |||
|
384 | ax.text(0.5 * (xax_lim[1] + xax_lim[0]), yax_lim[1], | |||
|
385 | ax.get_title(), | |||
|
386 | ha='center', va='bottom', fontsize=16) | |||
|
387 | ax.set_title('') | |||
|
388 | ||||
|
389 | Nlines = len(ax.lines) | |||
|
390 | lines = [xaxis, yaxis] + [ax.lines.pop(0) for i in range(Nlines)] | |||
|
391 | ||||
|
392 | for line in lines: | |||
|
393 | x, y = line.get_data() | |||
|
394 | ||||
|
395 | x_int, y_int = xkcd_line(x, y, xlim, ylim, | |||
|
396 | mag, f1, f2, f3) | |||
|
397 | ||||
|
398 | # create foreground and background line | |||
|
399 | lw = line.get_linewidth() | |||
|
400 | line.set_linewidth(2 * lw) | |||
|
401 | line.set_data(x_int, y_int) | |||
|
402 | ||||
|
403 | # don't add background line for axes | |||
|
404 | if (line is not xaxis) and (line is not yaxis): | |||
|
405 | line_bg = pl.Line2D(x_int, y_int, color=bgcolor, | |||
|
406 | linewidth=8 * lw) | |||
|
407 | ||||
|
408 | ax.add_line(line_bg) | |||
|
409 | ax.add_line(line) | |||
|
410 | ||||
|
411 | # Draw arrow-heads at the end of axes lines | |||
|
412 | arr1 = 0.03 * np.array([-1, 0, -1]) | |||
|
413 | arr2 = 0.02 * np.array([-1, 0, 1]) | |||
|
414 | ||||
|
415 | arr1[::2] += np.random.normal(0, 0.005, 2) | |||
|
416 | arr2[::2] += np.random.normal(0, 0.005, 2) | |||
|
417 | ||||
|
418 | x, y = xaxis.get_data() | |||
|
419 | if '+' in str(xaxis_arrow): | |||
|
420 | ax.plot(x[-1] + arr1 * xspan * aspect, | |||
|
421 | y[-1] + arr2 * yspan, | |||
|
422 | color='k', lw=2) | |||
|
423 | if '-' in str(xaxis_arrow): | |||
|
424 | ax.plot(x[0] - arr1 * xspan * aspect, | |||
|
425 | y[0] - arr2 * yspan, | |||
|
426 | color='k', lw=2) | |||
|
427 | ||||
|
428 | x, y = yaxis.get_data() | |||
|
429 | if '+' in str(yaxis_arrow): | |||
|
430 | ax.plot(x[-1] + arr2 * xspan * aspect, | |||
|
431 | y[-1] + arr1 * yspan, | |||
|
432 | color='k', lw=2) | |||
|
433 | if '-' in str(yaxis_arrow): | |||
|
434 | ax.plot(x[0] - arr2 * xspan * aspect, | |||
|
435 | y[0] - arr1 * yspan, | |||
|
436 | color='k', lw=2) | |||
|
437 | ||||
|
438 | # Change all the fonts to humor-sans. | |||
|
439 | prop = fm.FontProperties(fname='Humor-Sans.ttf', size=16) | |||
|
440 | for text in ax.texts: | |||
|
441 | text.set_fontproperties(prop) | |||
|
442 | ||||
|
443 | # modify legend | |||
|
444 | leg = ax.get_legend() | |||
|
445 | if leg is not None: | |||
|
446 | leg.set_frame_on(False) | |||
|
447 | ||||
|
448 | for child in leg.get_children(): | |||
|
449 | if isinstance(child, pl.Line2D): | |||
|
450 | x, y = child.get_data() | |||
|
451 | child.set_data(xkcd_line(x, y, mag=10, f1=100, f2=0.001)) | |||
|
452 | child.set_linewidth(2 * child.get_linewidth()) | |||
|
453 | if isinstance(child, pl.Text): | |||
|
454 | child.set_fontproperties(prop) | |||
|
455 | ||||
|
456 | # Set the axis limits | |||
|
457 | ax.set_xlim(xax_lim[0] - 0.1 * xspan, | |||
|
458 | xax_lim[1] + 0.1 * xspan) | |||
|
459 | ax.set_ylim(yax_lim[0] - 0.1 * yspan, | |||
|
460 | yax_lim[1] + 0.1 * yspan) | |||
|
461 | ||||
|
462 | # adjust the axes | |||
|
463 | ax.set_xticks([]) | |||
|
464 | ax.set_yticks([]) | |||
|
465 | ||||
|
466 | if expand_axes: | |||
|
467 | ax.figure.set_facecolor(bgcolor) | |||
|
468 | ax.set_axis_off() | |||
|
469 | ax.set_position([0, 0, 1, 1]) | |||
|
470 | ||||
|
471 | return ax | |||
|
472 | \end{lstlisting} | |||
|
473 | \end{codeinput} | |||
|
474 | \end{codecell} | |||
|
475 | \subsection{Testing it Out} | |||
|
476 | Let's test this out with a simple plot. We'll plot two curves, add some | |||
|
477 | labels, and then call \texttt{XKCDify} on the axis. I think the results | |||
|
478 | are pretty nice! | |||
|
479 | ||||
|
480 | \begin{codecell} | |||
|
481 | \begin{codeinput} | |||
|
482 | \begin{lstlisting} | |||
|
483 | %pylab inline | |||
|
484 | \end{lstlisting} | |||
|
485 | \end{codeinput} | |||
|
486 | \begin{codeoutput} | |||
|
487 | \begin{verbatim} | |||
|
488 | Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. | |||
|
489 | For more information, type 'help(pylab)'. | |||
|
490 | \end{verbatim} | |||
|
491 | \end{codeoutput} | |||
|
492 | \end{codecell} | |||
|
493 | \begin{codecell} | |||
|
494 | \begin{codeinput} | |||
|
495 | \begin{lstlisting} | |||
|
496 | np.random.seed(0) | |||
|
497 | ||||
|
498 | ax = pylab.axes() | |||
|
499 | ||||
|
500 | x = np.linspace(0, 10, 100) | |||
|
501 | ax.plot(x, np.sin(x) * np.exp(-0.1 * (x - 5) ** 2), 'b', lw=1, label='damped sine') | |||
|
502 | ax.plot(x, -np.cos(x) * np.exp(-0.1 * (x - 5) ** 2), 'r', lw=1, label='damped cosine') | |||
|
503 | ||||
|
504 | ax.set_title('check it out!') | |||
|
505 | ax.set_xlabel('x label') | |||
|
506 | ax.set_ylabel('y label') | |||
|
507 | ||||
|
508 | ax.legend(loc='lower right') | |||
|
509 | ||||
|
510 | ax.set_xlim(0, 10) | |||
|
511 | ax.set_ylim(-1.0, 1.0) | |||
|
512 | ||||
|
513 | #XKCDify the axes -- this operates in-place | |||
|
514 | XKCDify(ax, xaxis_loc=0.0, yaxis_loc=1.0, | |||
|
515 | xaxis_arrow='+-', yaxis_arrow='+-', | |||
|
516 | expand_axes=True) | |||
|
517 | ||||
|
518 | \end{lstlisting} | |||
|
519 | \end{codeinput} | |||
|
520 | \begin{codeoutput} | |||
|
521 | \begin{verbatim} | |||
|
522 | <matplotlib.axes.AxesSubplot at 0x2fecbd0> | |||
|
523 | \end{verbatim} | |||
|
524 | \begin{center} | |||
|
525 | \includegraphics[width=0.7\textwidth]{XKCD_plots_orig_files/XKCD_plots_orig_fig_00.png} | |||
|
526 | \par | |||
|
527 | \end{center} | |||
|
528 | \end{codeoutput} | |||
|
529 | \end{codecell} | |||
|
530 | \subsection{Duplicating an XKCD Comic} | |||
|
531 | Now let's see if we can use this to replicated an XKCD comic in | |||
|
532 | matplotlib. This is a good one: | |||
|
533 | ||||
|
534 | \begin{codecell} | |||
|
535 | \begin{codeinput} | |||
|
536 | \begin{lstlisting} | |||
|
537 | Image('http://imgs.xkcd.com/comics/front_door.png') | |||
|
538 | \end{lstlisting} | |||
|
539 | \end{codeinput} | |||
|
540 | \begin{codeoutput} | |||
|
541 | \begin{verbatim} | |||
|
542 | <IPython.core.display.Image at 0x2ff4a10> | |||
|
543 | \end{verbatim} | |||
|
544 | \end{codeoutput} | |||
|
545 | \end{codecell} | |||
|
546 | With the new \texttt{XKCDify} function, this is relatively easy to | |||
|
547 | replicate. The results are not exactly identical, but I think it | |||
|
548 | definitely gets the point across! | |||
|
549 | ||||
|
550 | \begin{codecell} | |||
|
551 | \begin{codeinput} | |||
|
552 | \begin{lstlisting} | |||
|
553 | # Some helper functions | |||
|
554 | def norm(x, x0, sigma): | |||
|
555 | return np.exp(-0.5 * (x - x0) ** 2 / sigma ** 2) | |||
|
556 | ||||
|
557 | def sigmoid(x, x0, alpha): | |||
|
558 | return 1. / (1. + np.exp(- (x - x0) / alpha)) | |||
|
559 | ||||
|
560 | # define the curves | |||
|
561 | x = np.linspace(0, 1, 100) | |||
|
562 | y1 = np.sqrt(norm(x, 0.7, 0.05)) + 0.2 * (1.5 - sigmoid(x, 0.8, 0.05)) | |||
|
563 | ||||
|
564 | y2 = 0.2 * norm(x, 0.5, 0.2) + np.sqrt(norm(x, 0.6, 0.05)) + 0.1 * (1 - sigmoid(x, 0.75, 0.05)) | |||
|
565 | ||||
|
566 | y3 = 0.05 + 1.4 * norm(x, 0.85, 0.08) | |||
|
567 | y3[x > 0.85] = 0.05 + 1.4 * norm(x[x > 0.85], 0.85, 0.3) | |||
|
568 | ||||
|
569 | # draw the curves | |||
|
570 | ax = pl.axes() | |||
|
571 | ax.plot(x, y1, c='gray') | |||
|
572 | ax.plot(x, y2, c='blue') | |||
|
573 | ax.plot(x, y3, c='red') | |||
|
574 | ||||
|
575 | ax.text(0.3, -0.1, "Yard") | |||
|
576 | ax.text(0.5, -0.1, "Steps") | |||
|
577 | ax.text(0.7, -0.1, "Door") | |||
|
578 | ax.text(0.9, -0.1, "Inside") | |||
|
579 | ||||
|
580 | ax.text(0.05, 1.1, "fear that\nthere's\nsomething\nbehind me") | |||
|
581 | ax.plot([0.15, 0.2], [1.0, 0.2], '-k', lw=0.5) | |||
|
582 | ||||
|
583 | ax.text(0.25, 0.8, "forward\nspeed") | |||
|
584 | ax.plot([0.32, 0.35], [0.75, 0.35], '-k', lw=0.5) | |||
|
585 | ||||
|
586 | ax.text(0.9, 0.4, "embarrassment") | |||
|
587 | ax.plot([1.0, 0.8], [0.55, 1.05], '-k', lw=0.5) | |||
|
588 | ||||
|
589 | ax.set_title("Walking back to my\nfront door at night:") | |||
|
590 | ||||
|
591 | ax.set_xlim(0, 1) | |||
|
592 | ax.set_ylim(0, 1.5) | |||
|
593 | ||||
|
594 | # modify all the axes elements in-place | |||
|
595 | XKCDify(ax, expand_axes=True) | |||
|
596 | ||||
|
597 | \end{lstlisting} | |||
|
598 | \end{codeinput} | |||
|
599 | \begin{codeoutput} | |||
|
600 | \begin{verbatim} | |||
|
601 | <matplotlib.axes.AxesSubplot at 0x2fef210> | |||
|
602 | \end{verbatim} | |||
|
603 | \begin{center} | |||
|
604 | \includegraphics[width=0.7\textwidth]{XKCD_plots_orig_files/XKCD_plots_orig_fig_01.png} | |||
|
605 | \par | |||
|
606 | \end{center} | |||
|
607 | \end{codeoutput} | |||
|
608 | \end{codecell} | |||
|
609 | Pretty good for a couple hours's work! | |||
|
610 | ||||
|
611 | I think the possibilities here are pretty limitless: this is going to be | |||
|
612 | a hugely useful and popular feature in matplotlib, especially when the | |||
|
613 | sketch artist PR is mature and part of the main package. I imagine using | |||
|
614 | this style of plot for schematic figures in presentations where the | |||
|
615 | normal crisp matplotlib lines look a bit too ``scientific''. I'm giving | |||
|
616 | a few talks at the end of the month\ldots{} maybe I'll even use some of | |||
|
617 | this code there. | |||
|
618 | ||||
|
619 | This post was written entirely in an IPython Notebook: the notebook file | |||
|
620 | is available for download | |||
|
621 | \href{http://jakevdp.github.com/downloads/notebooks/XKCD\_plots.ipynb}{here}. | |||
|
622 | For more information on blogging with notebooks in octopress, see my | |||
|
623 | \href{http://jakevdp.github.com/blog/2012/10/04/blogging-with-ipython/}{previous | |||
|
624 | post} on the subject. | |||
|
625 | ||||
|
626 | \end{document} |
@@ -0,0 +1,69 b'' | |||||
|
1 | <div class="highlight"><pre><span class="c">#! /usr/bin/env python</span> | |||
|
2 | <span class="sd">'''</span> | |||
|
3 | <span class="sd">github_team_calendar.py</span> | |||
|
4 | <span class="sd">Python program to scrape friends github to build team calendar for github</span> | |||
|
5 | <span class="sd">'''</span> | |||
|
6 | ||||
|
7 | ||||
|
8 | <span class="kn">import</span> <span class="nn">json</span> | |||
|
9 | <span class="kn">import</span> <span class="nn">requests</span> | |||
|
10 | <span class="kn">import</span> <span class="nn">pandas</span> <span class="kn">as</span> <span class="nn">pd</span> | |||
|
11 | ||||
|
12 | ||||
|
13 | <span class="k">def</span> <span class="nf">line_draw_target</span><span class="p">(</span><span class="n">target</span><span class="p">):</span> | |||
|
14 | <span class="n">github_url</span> <span class="o">=</span> <span class="s">'https://github.com/users/</span><span class="si">%s</span><span class="s">/contributions_calendar_data'</span> | |||
|
15 | <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">github_url</span> <span class="o">%</span> <span class="n">target</span><span class="p">)</span> | |||
|
16 | <span class="n">data</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">text</span><span class="p">)</span> | |||
|
17 | <span class="n">dates</span><span class="p">,</span> <span class="n">contributions</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">data</span><span class="p">)</span> | |||
|
18 | <span class="n">ts</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">(</span><span class="n">contributions</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="n">dates</span><span class="p">)</span> | |||
|
19 | <span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">ts</span><span class="p">)</span> | |||
|
20 | </pre></div> | |||
|
21 | ||||
|
22 | ||||
|
23 | ||||
|
24 | <div class="highlight"><pre><span class="n">target</span> <span class="o">=</span> <span class="s">"mikedewar"</span> | |||
|
25 | <span class="n">line_draw_target</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> | |||
|
26 | ||||
|
27 | </pre></div> | |||
|
28 | ||||
|
29 | ||||
|
30 | ||||
|
31 | ![](tests/ipynbref/data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_00.png) | |||
|
32 | ||||
|
33 | ||||
|
34 | <div class="highlight"><pre><span class="n">target</span> <span class="o">=</span> <span class="s">"drewconway"</span> | |||
|
35 | <span class="n">line_draw_target</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> | |||
|
36 | </pre></div> | |||
|
37 | ||||
|
38 | ||||
|
39 | ||||
|
40 | ![](tests/ipynbref/data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_01.png) | |||
|
41 | ||||
|
42 | ||||
|
43 | <div class="highlight"><pre><span class="n">target</span> <span class="o">=</span> <span class="s">"hmason"</span> | |||
|
44 | <span class="n">line_draw_target</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> | |||
|
45 | </pre></div> | |||
|
46 | ||||
|
47 | ||||
|
48 | ||||
|
49 | ![](tests/ipynbref/data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_02.png) | |||
|
50 | ||||
|
51 | ||||
|
52 | <div class="highlight"><pre><span class="n">target</span> <span class="o">=</span> <span class="s">"mbostock"</span> | |||
|
53 | <span class="n">line_draw_target</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> | |||
|
54 | </pre></div> | |||
|
55 | ||||
|
56 | ||||
|
57 | ||||
|
58 | ![](tests/ipynbref/data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_03.png) | |||
|
59 | ||||
|
60 | ||||
|
61 | <div class="highlight"><pre><span class="n">target</span> <span class="o">=</span> <span class="s">"amueller"</span> | |||
|
62 | <span class="n">line_draw_target</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> | |||
|
63 | </pre></div> | |||
|
64 | ||||
|
65 | ||||
|
66 | ||||
|
67 | ![](tests/ipynbref/data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_04.png) | |||
|
68 | ||||
|
69 |
@@ -0,0 +1,220 b'' | |||||
|
1 | %% This file was auto-generated by IPython. | |||
|
2 | %% Conversion from the original notebook file: | |||
|
3 | %% tests/ipynbref/data_geeks_team_calendar.orig.ipynb | |||
|
4 | %% | |||
|
5 | \documentclass[11pt,english]{article} | |||
|
6 | ||||
|
7 | %% This is the automatic preamble used by IPython. Note that it does *not* | |||
|
8 | %% include a documentclass declaration, that is added at runtime to the overall | |||
|
9 | %% document. | |||
|
10 | ||||
|
11 | \usepackage{amsmath} | |||
|
12 | \usepackage{amssymb} | |||
|
13 | \usepackage{graphicx} | |||
|
14 | \usepackage{ucs} | |||
|
15 | \usepackage[utf8x]{inputenc} | |||
|
16 | ||||
|
17 | % needed for markdown enumerations to work | |||
|
18 | \usepackage{enumerate} | |||
|
19 | ||||
|
20 | % Slightly bigger margins than the latex defaults | |||
|
21 | \usepackage{geometry} | |||
|
22 | \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm} | |||
|
23 | ||||
|
24 | % Define a few colors for use in code, links and cell shading | |||
|
25 | \usepackage{color} | |||
|
26 | \definecolor{orange}{cmyk}{0,0.4,0.8,0.2} | |||
|
27 | \definecolor{darkorange}{rgb}{.71,0.21,0.01} | |||
|
28 | \definecolor{darkgreen}{rgb}{.12,.54,.11} | |||
|
29 | \definecolor{myteal}{rgb}{.26, .44, .56} | |||
|
30 | \definecolor{gray}{gray}{0.45} | |||
|
31 | \definecolor{lightgray}{gray}{.95} | |||
|
32 | \definecolor{mediumgray}{gray}{.8} | |||
|
33 | \definecolor{inputbackground}{rgb}{.95, .95, .85} | |||
|
34 | \definecolor{outputbackground}{rgb}{.95, .95, .95} | |||
|
35 | \definecolor{traceback}{rgb}{1, .95, .95} | |||
|
36 | ||||
|
37 | % Framed environments for code cells (inputs, outputs, errors, ...). The | |||
|
38 | % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't | |||
|
39 | % randomly change them unless you're sure of the effect it will have. | |||
|
40 | \usepackage{framed} | |||
|
41 | ||||
|
42 | % remove extraneous vertical space in boxes | |||
|
43 | \setlength\fboxsep{0pt} | |||
|
44 | ||||
|
45 | % codecell is the whole input+output set of blocks that a Code cell can | |||
|
46 | % generate. | |||
|
47 | ||||
|
48 | % TODO: unfortunately, it seems that using a framed codecell environment breaks | |||
|
49 | % the ability of the frames inside of it to be broken across pages. This | |||
|
50 | % causes at least the problem of having lots of empty space at the bottom of | |||
|
51 | % pages as new frames are moved to the next page, and if a single frame is too | |||
|
52 | % long to fit on a page, will completely stop latex from compiling the | |||
|
53 | % document. So unless we figure out a solution to this, we'll have to instead | |||
|
54 | % leave the codecell env. as empty. I'm keeping the original codecell | |||
|
55 | % definition here (a thin vertical bar) for reference, in case we find a | |||
|
56 | % solution to the page break issue. | |||
|
57 | ||||
|
58 | %% \newenvironment{codecell}{% | |||
|
59 | %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}% | |||
|
60 | %% \MakeFramed{\vspace{-0.5em}}} | |||
|
61 | %% {\unskip\endMakeFramed} | |||
|
62 | ||||
|
63 | % For now, make this a no-op... | |||
|
64 | \newenvironment{codecell}{} | |||
|
65 | ||||
|
66 | \newenvironment{codeinput}{% | |||
|
67 | \def\FrameCommand{\colorbox{inputbackground}}% | |||
|
68 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
69 | {\unskip\endMakeFramed} | |||
|
70 | ||||
|
71 | \newenvironment{codeoutput}{% | |||
|
72 | \def\FrameCommand{\colorbox{outputbackground}}% | |||
|
73 | \vspace{-1.4em} | |||
|
74 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
75 | {\unskip\medskip\endMakeFramed} | |||
|
76 | ||||
|
77 | \newenvironment{traceback}{% | |||
|
78 | \def\FrameCommand{\colorbox{traceback}}% | |||
|
79 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |||
|
80 | {\endMakeFramed} | |||
|
81 | ||||
|
82 | % Use and configure listings package for nicely formatted code | |||
|
83 | \usepackage{listingsutf8} | |||
|
84 | \lstset{ | |||
|
85 | language=python, | |||
|
86 | inputencoding=utf8x, | |||
|
87 | extendedchars=\true, | |||
|
88 | aboveskip=\smallskipamount, | |||
|
89 | belowskip=\smallskipamount, | |||
|
90 | xleftmargin=2mm, | |||
|
91 | breaklines=true, | |||
|
92 | basicstyle=\small \ttfamily, | |||
|
93 | showstringspaces=false, | |||
|
94 | keywordstyle=\color{blue}\bfseries, | |||
|
95 | commentstyle=\color{myteal}, | |||
|
96 | stringstyle=\color{darkgreen}, | |||
|
97 | identifierstyle=\color{darkorange}, | |||
|
98 | columns=fullflexible, % tighter character kerning, like verb | |||
|
99 | } | |||
|
100 | ||||
|
101 | % The hyperref package gives us a pdf with properly built | |||
|
102 | % internal navigation ('pdf bookmarks' for the table of contents, | |||
|
103 | % internal cross-reference links, web links for URLs, etc.) | |||
|
104 | \usepackage{hyperref} | |||
|
105 | \hypersetup{ | |||
|
106 | breaklinks=true, % so long urls are correctly broken across lines | |||
|
107 | colorlinks=true, | |||
|
108 | urlcolor=blue, | |||
|
109 | linkcolor=darkorange, | |||
|
110 | citecolor=darkgreen, | |||
|
111 | } | |||
|
112 | ||||
|
113 | % hardcode size of all verbatim environments to be a bit smaller | |||
|
114 | \makeatletter | |||
|
115 | \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt | |||
|
116 | \makeatother | |||
|
117 | ||||
|
118 | % Prevent overflowing lines due to urls and other hard-to-break entities. | |||
|
119 | \sloppy | |||
|
120 | ||||
|
121 | \begin{document} | |||
|
122 | ||||
|
123 | \begin{codecell} | |||
|
124 | \begin{codeinput} | |||
|
125 | \begin{lstlisting} | |||
|
126 | #! /usr/bin/env python | |||
|
127 | ''' | |||
|
128 | github_team_calendar.py | |||
|
129 | Python program to scrape friends github to build team calendar for github | |||
|
130 | ''' | |||
|
131 | ||||
|
132 | ||||
|
133 | import json | |||
|
134 | import requests | |||
|
135 | import pandas as pd | |||
|
136 | ||||
|
137 | ||||
|
138 | def line_draw_target(target): | |||
|
139 | github_url = 'https://github.com/users/%s/contributions_calendar_data' | |||
|
140 | r = requests.get(github_url % target) | |||
|
141 | data = json.loads(r.text) | |||
|
142 | dates, contributions = zip(*data) | |||
|
143 | ts = pd.Series(contributions, index=dates) | |||
|
144 | plt.plot(ts) | |||
|
145 | \end{lstlisting} | |||
|
146 | \end{codeinput} | |||
|
147 | \end{codecell} | |||
|
148 | \begin{codecell} | |||
|
149 | \begin{codeinput} | |||
|
150 | \begin{lstlisting} | |||
|
151 | target = "mikedewar" | |||
|
152 | line_draw_target(target) | |||
|
153 | ||||
|
154 | \end{lstlisting} | |||
|
155 | \end{codeinput} | |||
|
156 | \begin{codeoutput} | |||
|
157 | \begin{center} | |||
|
158 | \includegraphics[width=0.7\textwidth]{data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_00.png} | |||
|
159 | \par | |||
|
160 | \end{center} | |||
|
161 | \end{codeoutput} | |||
|
162 | \end{codecell} | |||
|
163 | \begin{codecell} | |||
|
164 | \begin{codeinput} | |||
|
165 | \begin{lstlisting} | |||
|
166 | target = "drewconway" | |||
|
167 | line_draw_target(target) | |||
|
168 | \end{lstlisting} | |||
|
169 | \end{codeinput} | |||
|
170 | \begin{codeoutput} | |||
|
171 | \begin{center} | |||
|
172 | \includegraphics[width=0.7\textwidth]{data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_01.png} | |||
|
173 | \par | |||
|
174 | \end{center} | |||
|
175 | \end{codeoutput} | |||
|
176 | \end{codecell} | |||
|
177 | \begin{codecell} | |||
|
178 | \begin{codeinput} | |||
|
179 | \begin{lstlisting} | |||
|
180 | target = "hmason" | |||
|
181 | line_draw_target(target) | |||
|
182 | \end{lstlisting} | |||
|
183 | \end{codeinput} | |||
|
184 | \begin{codeoutput} | |||
|
185 | \begin{center} | |||
|
186 | \includegraphics[width=0.7\textwidth]{data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_02.png} | |||
|
187 | \par | |||
|
188 | \end{center} | |||
|
189 | \end{codeoutput} | |||
|
190 | \end{codecell} | |||
|
191 | \begin{codecell} | |||
|
192 | \begin{codeinput} | |||
|
193 | \begin{lstlisting} | |||
|
194 | target = "mbostock" | |||
|
195 | line_draw_target(target) | |||
|
196 | \end{lstlisting} | |||
|
197 | \end{codeinput} | |||
|
198 | \begin{codeoutput} | |||
|
199 | \begin{center} | |||
|
200 | \includegraphics[width=0.7\textwidth]{data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_03.png} | |||
|
201 | \par | |||
|
202 | \end{center} | |||
|
203 | \end{codeoutput} | |||
|
204 | \end{codecell} | |||
|
205 | \begin{codecell} | |||
|
206 | \begin{codeinput} | |||
|
207 | \begin{lstlisting} | |||
|
208 | target = "amueller" | |||
|
209 | line_draw_target(target) | |||
|
210 | \end{lstlisting} | |||
|
211 | \end{codeinput} | |||
|
212 | \begin{codeoutput} | |||
|
213 | \begin{center} | |||
|
214 | \includegraphics[width=0.7\textwidth]{data_geeks_team_calendar_orig_files/data_geeks_team_calendar_orig_fig_04.png} | |||
|
215 | \par | |||
|
216 | \end{center} | |||
|
217 | \end{codeoutput} | |||
|
218 | \end{codecell} | |||
|
219 | ||||
|
220 | \end{document} |
General Comments 0
You need to be logged in to leave comments.
Login now