__AUTHORS__ = {'am': ("Andrea Marino", 
                      "andrea.marino@unifi.it",),
               'mn': ("Massimo Nocentini", 
                      "massimo.nocentini@unifi.it", 
                      "https://github.com/massimo-nocentini/",)}

__KEYWORDS__ = ['Python', 'Jupyter', 'notebooks', 'keynote',]

"""
Explanation: <p>
<img src="http://www.cerm.unifi.it/chianti/images/logo%20unifi_positivo.jpg" 
        alt="UniFI logo" style="float: left; width: 20%; height: 20%;">
<div align="right">

<small>
Massimo Nocentini, PhD.
<br><br>
February 7, 2020: init
</small>
</div>
</p>
<br>
<br>
<div align="center">
<b>Abstract</b><br>
A (very concise) introduction to the Python ecosystem.
</div>
End of explanation
"""


outline = []
outline.append('Hello!')
outline.append('Python')
outline.append('Whys and refs')
outline.append('On the shoulders of giants')
outline.append('Set the env up')
outline.append('Notebooks')
outline.append('Course agenda')

import this

"""
Explanation: <center><img src="https://upload.wikimedia.org/wikipedia/commons/c/c3/Python-logo-notext.svg"></center>
End of explanation
"""


%lsmagic

"""
Explanation: past and present
From https://en.wikipedia.org/wiki/Python_(programming_language)
- Python is an interpreted, high-level, general-purpose programming language. Created by Guido van Rossum and first released in 1991, Python's design philosophy emphasizes code readability with its notable use of significant whitespace. Its language constructs and object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects.
- Python is dynamically typed and garbage-collected. It supports multiple programming paradigms, including procedural, object-oriented, and functional programming. Python is often described as a "batteries included" language due to its comprehensive standard library.
- Python was conceived in the late 1980s as a successor to the ABC language. Python 2.0, released in 2000, introduced features like list comprehensions and a garbage collection system capable of collecting reference cycles. Python 3.0, released in 2008, was a major revision of the language that is not completely backward-compatible, and much Python 2 code does not run unmodified on Python 3.
- PSF Python Brochure Project
From https://www.python.org/

Functions Defined. The core of extensible programming is defining functions. Python allows mandatory and optional arguments, keyword arguments, and even arbitrary argument lists.
Compound Data Types. Lists (known as arrays in other languages) are one of the compound data types that Python understands. Lists can be indexed, sliced and manipulated with other built-in functions.
Intuitive Interpretation. Calculations are simple with Python, and expression syntax is straightforward: the operators +, -, * and / work as expected; parentheses () can be used for grouping.
Quick & Easy to Learn. Experienced programmers in any other language can pick up Python very quickly, and beginners find the clean syntax and indentation structure easy to learn.
All the Flow You’d Expect. Python knows the usual control flow statements that other languages speak — if, for, while and range — with some of its own twists, of course. 

Some supporting quotes here.
From https://docs.python.org/3/

beware of shadows
Python can be installed in many different ways with respect to different needs.
- https://www.anaconda.com/ 
- https://www.spyder-ide.org/
- https://www.sagemath.org/
We advice to stick to the official one for the sake of being self contained and use an unified environment.
All such distributions customize the base package for domain-specific domains, in the future you will be able to take into account the one that best suites your needs; for the present, trust the default one.
Therefore, go head and install the Python interpreter.
https://www.python.org/downloads/ 

our working environment
There are many different possibilities to run Python programs:
- edit the program my-script.py and then invoke the bare bone<br>interpreter with $ python my-script.py
- use an Integrated Development Environment (IDE from now on):
  - https://www.spyder-ide.org/
  - https://www.jetbrains.com/pycharm/
  - https://vscodium.com/
Whatever you feel comfortable is okay.
The important thing is that you play in a safe environment.
Quoting the official doc:

Python provides support for creating lightweight “virtual environments” with their own site directories, optionally isolated from system site directories. Each virtual environment has its own Python binary (which matches the version of the binary that was used to create this environment) and can have its own independent set of installed Python packages in its site directories.

Those environments allow you to freely (un)install modules and customize the interpreter, without apporting those changes to the system installation.
https://docs.python.org/3/tutorial/venv.html

bash
$ python3 -m venv unifi-env # creates a virtual environment
bash
$ source unifi-env/bin/activate # enter into our safe environment
bash
(unifi-env) $ pip install ipython jupyter matplotlib numpy scipy \
                sympy pandas # install some packages
bash
(unifi-env) $ python do-I-halt-or-not.py # run your cool stuff
bash
(unifi-env) $ deactivate # exit the environment
bash
$ # back to the usual shell
Notebooks

Notebooks are interactive web pages, served by a backend process called Jupyter
formely, everything within IPython. Now, refactored in many little projects:
Jupyter is just a backend, a kind of proxy built using zeroqm messaging system
Jupyter interact with pluggable kernels, namely interpreters for the choosen programming language
tying the knot: you can write and evaluate code directly on the web page
pragmatically: a notebook is a set of cells, containing both code and structured text

Jupyter architecture, precisely

The Notebook Document Format<br>
  Jupyter Notebooks are an open document format based on JSON. They contain a complete record of the user's   sessions and embed code, narrative text, equations and rich output.
Interactive Computing Protocol<br>
  The Notebook communicates with computational Kernels using the Interactive Computing Protocol, an open network protocol based on JSON data over ZMQ and WebSockets.
The Kernel<br>
  Kernels are processes that run interactive code in a particular programming language and return output to the user. Kernels also respond to tab completion and introspection requests.

Code cells
The following is a code cell, it has an identifier on the left In [ ]: and a blank space on the right where we can type code in:
Magics
All the following magics can be used in any session using the ipython interpreter:
End of explanation
"""


%quickref

"""
Explanation: For a nicer description evaluate the following cell:
End of explanation
"""


%%bash

jupyter-notebook -h

"""
Explanation: %%bash
To start a Jupyter process to serve our notebooks:
End of explanation
"""


%%latex

\begin{eqnarray}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\
\nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0 
\end{eqnarray}

"""
Explanation: %%latex
Just a bit of math, beautified:
End of explanation
"""


initial_conditions = {0:0, 1:1}

def make_fibonacci(maxsize=None):
    '''Make the Fibonacci sequence using memoization of not (set `maxsize` arg to 0)'''
    
    @lru_cache(maxsize=maxsize)
    def fibonacci(n):
        return fibonacci(n-1)  + fibonacci(n-2) if n not in initial_conditions else initial_conditions[n]
    return fibonacci

%%timeit 
fibonacci_memoization = make_fibonacci(maxsize=None)
[fibonacci_memoization(n) for n in range(20)]

%%timeit
fibonacci_naive = make_fibonacci(maxsize=0)
[fibonacci_naive(n) for n in range(20)]

"""
Explanation: %%timeit
Time an example from your lab sessions (link):
End of explanation
"""


import IPython.display

dir(IPython.display)[:10]

from IPython.display import Math
Math(r'F(k) = \int_{-\infty}^{\infty} f(x) e^{2\pi i k} dx')

from IPython.display import Latex
Latex(r"""\begin{eqnarray}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\
\nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0 
\end{eqnarray}""")

from IPython.display import HTML
oeis_url=r"http://oeis.org/"
HTML(r'<iframe width="100%" height="500" src="{url}" />'.format(url=oeis_url))

"""
Explanation: Pretty printers
Write code that writes your notebook, beautifully:
End of explanation
"""


%%bash

jupyter-nbconvert -h

"""
Explanation: nbviewer
If you publish your notebooks (Github, huh?), it is possible to render them as static web documents:

using the proxy http://nbviewer.jupyter.org/;
from there you can browse a collection of tutorials, books and notebooks targeting different PL,
altough we're mainly interested in those using Python, of course.

nbconvert
It is possible to convert a notebook to various formats:
End of explanation
"""


