pip install ipython-notebook

"""
Explanation: A Review of EuroSciPy2015
0. IPython Notebooks
1. Tutorial 1: An Introduction to Python (Joris Vankerschaver)
2. Tutorial 2: Never get in a data battle without Numpy arrays (Valerio Maggio)
3. numexpr
4. Interesting talks
0. Jupyter aka IPython Notebook


Interactive programming interface


Simultaneous development & documentation


All tutorials and most lectures at EuroSciPy2015 were given using IPython Notebooks.


We have adopted the Notebook for this presentation as a practical exercise.
End of explanation
"""


ipython notebook

"""
Explanation: Create a local host for the notebook in the directory of interest by running the command:
End of explanation
"""


# Mutable objects can be changed in place (e.g. lists),
# Immutable objects can NOT (e.g. ints, strings, tuples)
tup = ('a','0','@')
tup

tup[0] = 8

record = {}
record['first'] = 'Alan'
record['last'] = 'Turing'
record

record.update({'workplace':'Bletchley Park'})
record

# Comma after print statement removes implicit \n, prints to same line
for x in range(0,4):
    print x,

# xrange(#) more efficient than range(#), because:
# range() creates the whole sequence of numbers,
# while xrange() creates them as needed!

%timeit range(1000000)

%timeit xrange(1000000)

# Namespaces are evil
pi = 3.14
from numpy import pi
pi

"""
Explanation: Images, data files, etc. should be stored in a subdirectory of the Notebook host.
1. Tutorial #1: An Introduction to Python (Joris Vankerschaver)
IPython Notebook: https://github.com/jvkersch/python-tutorial-files
An overview of basic Python syntax and data structures, including:
- lists, tuples, dictionaries
- mutable vs immutable objects
- set, enumerate
- read from / write to files
- namespaces
End of explanation
"""


range?

"""
Explanation: Accessing Python's Source Code
cf. http://stackoverflow.com/questions/8608587/finding-the-source-code-for-built-in-python-functions
We can get help for a built-in Python function, such as range, with a single question mark:
End of explanation
"""


# import inspect
# inspect.getsourcefile(range) # doesn't work for built-in functions

# Python's built-in "Counter" class defines the control flow of iterators,
# used in functions such as "for i in range(0,10) ..."

class Counter(object):
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        'Returns itself as an iterator object'
        return self

    def __next__(self):
        'Returns the next value till current is lower than high'
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1

"""
Explanation: ...and we can read the source code of built-in functions by downloading the source from the Python.org Mercurial repositories): https://hg.python.org/
End of explanation
"""


for i in range(0,10):
    print i*i

# List comprehension (with filter)
[a*2 for a in range(0,10) if a>3]

"""
Explanation: We can view the source code for a particular function, such as range, in the Python.org Mercurial Repository: https://hg.python.org/cpython/file/c6880edaf6f3/Objects/rangeobject.c
End of explanation
"""


# The Zen of Python
import this

"""
Explanation: Sneak-peek @ Advanced Topics

NumPy & SciPy
Pandas
Cython
Translate Python scripts into C code, and compile to machine code.
End of explanation
"""


# We can infer the data type of an array structure (but not of int, list, etc.)
import numpy as np

a = np.array([1, 2, 3], dtype=np.int16)
a.dtype

arev = a[::-1]
arev

# Typecast variables into float, complex numbers,
b = np.float64(64)
c = np.complex(b)
print "R(c) = ", c.real
print "I(c) = ", c.imag

# Specify type of array elements
x = np.ones(4, 'int8')
x

# Wrap-around
x[0] = 256
x

# Define a new record and create an array of corresponding data types
rt = np.dtype([('artist', np.str_, 40),('title', np.str_, 40), ('year', np.int16)])
music = np.array([('John Cage','4\'33\'\'',1952)], dtype=rt)
music

"""
Explanation: 2. Tutorial 2: Never get in a data battle without Numpy arrays (Valerio Maggio)
IPython Notebook: https://github.com/leriomaggio/numpy_euroscipy2015
Arrays and Data Types
End of explanation
"""


# Flatten a matrix into a 1-D array
r = np.array([[1, 2, 3], [4, 5, 6]])
r.ravel()

# Save a .csv file using arbitrary precision
M = np.random.rand(3,3)
np.savetxt("data/random-matrix2.csv", M, fmt='%.5f')

# Create a matrix using list comprehension
coolmx = np.array([[10*j+i for i in range(6)] for j in range(6)])
coolmx

"""
Explanation: Matrix Tricks
End of explanation
"""


# Machine Learning in Python is a oneliner!
centroids, variance = vq.kmeans(data, 3)
#... after preparing the data and importing the scikit-learn package

"""
Explanation: Memmapping
@ https://github.com/leriomaggio/numpy_euroscipy2015/blob/master/05_Memmapping.ipynb
Machine Learning with SciKit-Learn

Applying the K-means algorithm to the Iris dataset
@ https://github.com/leriomaggio/numpy_euroscipy2015/blob/master/07_0_MachineLearning_Data.ipynb
End of explanation
"""


import numexpr as ne
import numpy as np

a = np.arange(1e8)
b = np.arange(1e8)

print "NumPy   >> " 
%timeit a**2 + b**2 + 2*a*b

print "NumExpr >> "
%timeit ne.evaluate('a**2 + b**2 + 2*a*b')

"""
Explanation: A look into the future

Blaze will supersede NumPy for Big Data
@ https://github.com/leriomaggio/numpy_euroscipy2015/blob/master/08_A_look_at_the_future.ipynb

numpy-100
"...a quick reference for new and old users and to provide also a set of exercices for those who teach."
https://github.com/rougier/numpy-100
3. numexpr
@ https://github.com/pydata/numexpr (previously @ https://code.google.com/p/numexpr/)

JIT (Just-in-time) compilation for significant speed-up of numerial calculations

numexpr evaluates multiple-operator array expressions many times faster than NumPy can. It accepts the expression as a string, analyzes it, rewrites it more efficiently, and compiles it on the fly into code for its internal virtual machine (VM). Due to its integrated just-in-time (JIT) compiler, it does not require a compiler at runtime.


Multithreading to make use of multiple CPU cores


numexpr implements support for multi-threading computations straight into its internal virtual machine, written in C. This allows to bypass the GIL in Python, and allows near-optimal parallel performance in your vector expressions, most specially on CPU-bounded operations (memory-bounded ones were already the strong point of numexpr).


Can be used to evaluate expressions in NumPy and Pandas


cf. https://github.com/leriomaggio/numpy_euroscipy2015/blob/master/06_Numexpr.ipynb
The Speed of NumExpr

The speed advantage of NumExpr is due to using fewer temporary variables to store data. Instead of using temp variables, the results are stored successively in the output argument.
For this reason, NumExpr outperforms standard Python when array sizes are larger than the processor cache. For small computations, it is actually slower...
...so use only when necessary!
More info about how it is done: https://github.com/pydata/numexpr#how-numexpr-can-achieve-such-a-high-performance
End of explanation
"""


