%%writefile hello.py
#!/usr/bin/env python
def printHello():
    print "Hello World"
    
print "File Loaded"

"""
Explanation: Note:  This is basically a grab-bag of things...  
Advanced iPython
iPython: interactive Python
Many different ways to work with Python:

type 'python' from the command line
run a python script/program from the command line ('python my_prog.py')

iPython adds functionallity and interactivity to python that makes it more useful in your day-to-day life.
It is an interactive shell for the Python programming language that offers enhanced introspection, additional shell syntax, tab completion and rich history.
Fernando Pérez, Brian E. Granger, IPython: A System for Interactive Scientific Computing, Computing in Science and Engineering, vol. 9, no. 3, pp. 21-29, May/June 2007, doi:10.1109/MCSE.2007.53. URL: http://ipython.org

python shell
Go out of the notebook and play with the python shell.  Show some of the limitations.
run a python script
Go out of the notebook and create a python script to run.
hello.py:
End of explanation
"""


cat mystuff.ipynb

"""
Explanation: ipython shell
Tab Completion and History Search is Great

Start typing and use the 'tab' key for auto complete.  Can use this on python functions, modules, variables, files, and more...
iPython stores history.  You can search it (ctrl-r) or you can use the up and down arrows.

Run a file
Run it and get access to the functions and modules inside
(notice I used 'tab' completion).  Try using the 'up' arrow and running it again.
Here's something else useful:
(what did this do...)
Note that this is a 'magic command' - I'll talk about this in a bit.
The four most helpful commands
<table>
<thead valign="bottom">
<tr class="row-odd"><th class="head">command</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>?</td>
<td>Introduction and overview of IPython&#8217;s features.</td>
</tr>
<tr class="row-odd"><td>%quickref</td>
<td>Quick reference.</td>
</tr>
<tr class="row-even"><td>help</td>
<td>Python&#8217;s own help system.</td>
</tr>
<tr class="row-odd"><td>object?</td>
<td>Details about &#8216;object&#8217;, use &#8216;object??&#8217; for extra details.</td>
</tr>
</tbody>
</table>

The notebook (ipython notebook or jupyter)
How does this work...  Let's look at what it says about itself (from http://ipython.org/ipython-doc/3/notebook/notebook.html)
Introduction
The notebook extends the console-based approach to interactive computing in a qualitatively new direction, providing a web-based application suitable for capturing the whole computation process: developing, documenting, and executing code, as well as communicating the results. The IPython notebook combines two components:
A web application: a browser-based tool for interactive authoring of documents which combine explanatory text, mathematics, computations and their rich media output.
Notebook documents: a representation of all content visible in the web application, including inputs and outputs of the computations, explanatory text, mathematics, images, and rich media representations of objects.
Main features of the web application

In-browser editing for code, with automatic syntax highlighting, indentation, and tab completion/introspection.
The ability to execute code from the browser, with the results of computations attached to the code which generated them.
Displaying the result of computation using rich media representations, such as HTML, LaTeX, PNG, SVG, etc. For example, publication-quality figures rendered by the matplotlib library, 
can be included inline.
In-browser editing for rich text using the Markdown markup language, which can provide commentary for the code, is not limited to plain text.
The ability to easily include mathematical notation within markdown cells using LaTeX, and rendered natively by MathJax.

What is a notebook:
It's just a JSON formatted text file.  Let's look at the really simple one we just created from the iPython interpreter.
End of explanation
"""


2+4 

"""
Explanation: Ok, backup, how do I interact with the notebook and what is it?
First step, the notebook is made up of cells.  These cells can be of different types.  If you create a cell (click the '+' sign on the menu bar) then you can use the pull down to make it either 

code: actual python code you want to execute
markdown: notes in markdown format
raw: raw text (like code you want to display like the json code above)
heading: you can make a cell a heading

Let's play with the four types below:
Code:
End of explanation
"""


%timeit range(1000) 

%%timeit x = range(10000)
max(x)

%lsmagic

"""
Explanation: So, you exectued this by hitting the 'play' button in the tool bar or you used 'shift-enter'.  Some other ways: 

Shift-enter: run cell, go to next cell
Ctrl-enter: run cell in place
Alt-enter: run cell, insert below

Markdown
Fancy Markdown Cell
code code code


Bullet 1
Bullet 2
numbered
numbered

Some verbose words
Markdown Reference
Raw text
Can I do this quickly?
Yep - take a look at the 'Keyboard Shortcuts' menu.  
First of all, there are two 'modes': 'command' and 'edit'.  When you're in a cell, you're in 'edit mode' and when you're out of the cell you're in 'command mode'  You go into 'command mode' by hitting 'esc' and into edit by hitting 'return'.  Try it a couple times.  Move up and down through cells with the arrow keys when in 'command mode'.
go through the keyboard shortcuts
My Favs:
* r,m,y in command mode
* ⌘Z : undo
* d: delete
* (also, cntl-e and cntl-a work in a cell, if you live in unix, you'll understand why this is awesome)
Once you start getting the shortcuts down, you're crazy productive.
Exercise: Copy and Paste is Neat
Try copy and pasting our for loop code from the iPython console into a cell (only use the keyboard):
The menubar and toolbar
Let's go over all of these functions and talk about what they do...
It's like Magic (functions)
IPython has a set of predefined ‘magic functions’ that you can call with a command line style syntax. There are two kinds of magics, line-oriented and cell-oriented. Line magics are prefixed with the % character and work much like OS command-line calls: they get as an argument the rest of the line, where arguments are passed without parentheses or quotes. Cell magics are prefixed with a double %%, and they are functions that get as an argument not only the rest of the line, but also the lines below it in a separate argument.
Examples:
You've already seen a few magic functions above (%run and %notebook).  Here's some others.
End of explanation
"""


ls

%matplotlib inline

"""
Explanation: My favs...
End of explanation
"""


%%capture capt
from __future__ import print_function
import sys
print('Hello stdout')
print('and stderr', file=sys.stderr)

capt.stdout, capt.stderr

capt.show()

"""
Explanation: MUCHS INFOS: https://ipython.org/ipython-doc/dev/interactive/magics.html
Some others to try:  %edit, %capture
End of explanation
"""


%%script python
import sys
print 'hello from Python %s' % sys.version

%%bash
echo "hello from $BASH"

"""
Explanation: Magics for running code under other interpreters
IPython has a %%script cell magic, which lets you run a cell in a subprocess of any interpreter on your system, such as: bash, ruby, perl, zsh, R, etc.
It can even be a script of your own, which expects input on stdin.
To use it, simply pass a path or shell command to the program you want to run on the %%script line, and the rest of the cell will be run by that script, and stdout/err from the subprocess are captured and displayed.
End of explanation
"""


%%script ./lnum.py
my first line
my second
more

"""
Explanation: Exercise: write your own script that numbers input lines
Write a file, called lnum.py, such that the following cell works as shown (hint: don't forget about the executable bit!):
End of explanation
"""


a = 3

b = 4

a + b

a*b

a - b

_

___

_49

Out[62]

_i

In[50]

"""
Explanation: Hints:

Useful function: sys.stdin.readlines()
Another useful function: enumerate()

You could use the notebook to query what these do...
Out and In
You can access the input and output of previous cells.
End of explanation
"""


!python --version

!ping www.google.com

"""
Explanation: Running Shell Commands
There are some magics for some shell commands (like ls and pwd - this is relaly great on a windows system by the way) but you can also run arbitrary system commands with a '!'.
End of explanation
"""


import time
time.sleep(10)

"""
Explanation: Managing the IPython Kernel
Code is run in a separate process called the IPython Kernel.  The Kernel can be interrupted or restarted.  Try running the following cell and then hit the "Stop" button in the toolbar above.
End of explanation
"""


import sys
from ctypes import CDLL
# This will crash a Linux or Mac system; equivalent calls can be made on Windows
dll = 'dylib' if sys.platform == 'darwin' else 'so.6'
libc = CDLL("libc.%s" % dll) 
libc.time(-1)  # BOOM!!

"""
Explanation: If the Kernel dies you will be prompted to restart it. Here we call the low-level system libc.time routine with the wrong argument via
ctypes to segfault the Python interpreter:
End of explanation
"""


!python --version

!ipython --version

"""
Explanation: Side note on versions
There can be (and probably are) different python versions and ipython versions.  This is normal.  Don't Panic.  Everybody got their towel?
End of explanation
"""


%load http://matplotlib.sourceforge.net/mpl_examples/pylab_examples/integral_demo.py

"""
Explanation: I promised you latex!
You just need to surround equations in markdown with '$' signs.
$y = x^{2}$
$\frac{dN}{dE} = \frac{N_{\text peak}}{E_{\text peak}} (E/E_{\text peak})^{\gamma} (e^{1 - E/E_{\text peak}})^{\gamma+2}$
Note that it's using MathJax for the rendering so if you're offline, you might not get latex.
Running a remote file!
Note: do this after the plotting bit.
End of explanation
"""


%pdb

"""
Explanation: Debugging
iPython has a powerful debugger.  Let's see how it works a bit:
When iPython encounters an exception (in this case a ZeroDivisionError) it'll drop us into a pdb session if we use the %debug magic.  Commands:

? for "help"
? s for "help for command s"
l for "some more context"
s for "step into"
n for "step over"
c for "continue to next breakpoint"

You can also turn on automatic debugging.
End of explanation
"""


!ipython nbconvert mystuff.ipynb --to pdf

"""
Explanation: Lots of useful features in the python debugger (and could probably do with a seperate lecture).  We'll save that for another day...
nbconvert
You can convert notebooks into lots of different formats with the nbconvert command (type 'ipython nbconvert' for all of the options).  Example:
End of explanation
"""


#Note that I had to install cython to get this to work.
# try doing 'conda update cython' if you get an error

%load_ext Cython

%%cython
cimport numpy

cpdef cysum(numpy.ndarray[double] A):
    """Compute the sum of an array"""
    cdef double a=0
    for i in range(A.shape[0]):
        a += A[i]
    return a

def pysum(A):
    """Compute the sum of an array"""
    a = 0
    for i in range(A.shape[0]):
        a += A[i]
    return a

import numpy as np

for sz in (100, 1000, 10000):
    A = np.random.random(sz)
    print("==>Python %i" % sz, end=' ')
    %timeit pysum(A)
    print("==>np.sum %i" % sz, end=' ')
    %timeit A.sum()
    print("==>Cython %i" % sz, end=' ')
    %timeit cysum(A)

"""
Explanation: The %cython magic
Probably the most important magic is the %cython magic. The %%cython magic uses manages everything using temporary files in the ~/.ipython/cython/ directory. All of the symbols in the Cython module are imported automatically by the magic.
cython is a way of running c code inside iPython.  Sometimes a c function can be much faster than the equivalent function in python.
End of explanation
"""


