def mafonction(a, b):
    print("Je divise")
    return a/b # indentation de l'intérieur de la fonction = on est toujours dans la fonction
print("fini de définir ma fonction") # indentation de l'extérieur de la fonction donc la fonction est finie

mafonction(5,2)

"""
Explanation: Initiation à Python
Cette page web est en fait un notebook, visualisé par Jupyter et dont le code est exécuté par IPython. Vous l'avez ouvert dans votre navigateur après avoir tapé dans votre console
jupyter notebook
et sélectionné le fichier initiation.ipynb.
Le texte que vous êtes en train de lire est contenu dans une cellule de type Markdown qui permet un formattage aisé du texte, y compris des formules $\LaTeX$ en ligne comme $\sum\gamma_i^2$ ou en equations séprarées:
$$\frac{\ln \pi}{12}.$$
Un notebook peut donc contenir deux types de cellules:
 - Markdown 
 - Code
Vous pouvez sélectionner le type de cellule dans le menu déroulant de la barre d'outils ci-dessus. En utilisant le menu Insert, vous pouvez ajouter des cellules. Les cellules de code s'exécutent en faisant Maj+Entrer. Les cellules Markdown se formattent de la même façon et on retourne à l'édition de leur contenu par un double clic.
Les fonctions
En Python, tout est dans l'indentation
End of explanation
"""


def mafonction(a, b):
    """Division de a par b"""
    return a/b

mafonction?

"""
Explanation: On peut documenter ses propres fonctions.
End of explanation
"""


def mafonction(a, b=2):
    """Division de a par b"""
    return a/b
print(mafonction(5))
print(mafonction(5,10))

mafonction?

"""
Explanation: Il est possible d'avoir des arguments par défaut.
End of explanation
"""


def mafonction(a, b=2, diviser=True):
    """Division de a par b.
    Si on ne divise pas, on retourne a et b""" #on a le droit de passer à la ligne si on a ouvert 3 guillemets
    if diviser:
        return a/b
    else:
        return a,b
print(mafonction(5))
print(mafonction(5, 10))
print(mafonction(5, diviser=False))

"""
Explanation: Un peu plus complexe : on imbrique deux indentations et on a 2 arguments avec des valeurs par défaut.
End of explanation
"""


a = "coucou" #definition de l'objet. Pas besoin de donner son type
print(a) #affichage de toute la chaîne de caractères
print(a[0]) #affichage du premier élément. Attention, les indices commencent à 0
print(a[1])
print(a[-1]) #affichage du dernier élément. On utilise des entiers négatifs pour partir de la fin
print(a[1:]) #affichage à partir de l'élément 1
print(a[:3]) #jusqu'à l'élément 3 non inclu. Equivalent mais plus court que a[0:3]
print(a[:-1]) #jusqu'au dernier élément non inclu
print(a[::2]) #tous les 2 éléments. Equivalent mais plus court que a[0:len(a):2]
print(a[1:-1:3]) #à partir de l'élement 1, jusqu'au dernier élément non inclu, tous les 3 éléments

print("cou" + "cou") #concaténation de deux chaînes de caractères
print("cou" * 2) # répétition 2 fois

"""
Explanation: Jouer avec les chaînes de caractères
Indexation, sous-chaîne et concaténation
End of explanation
"""


#premiere boucle for. On itère directement sur les caractères de la chaîne.
for lettre in a:
    print(lettre)
    print("-") # indentation de l'intérieur de la boucle = on est toujours dans la boucle
print("c'est fini") # indentation de l'extérieur de la boucle donc la boucle est finie

for lettre in a[::-1]:
    print(lettre)

for i,lettre in enumerate(a): #i est l'indice de l'itération dans la boucle
    print(i,lettre)

for u,v in zip(a, "colibri"): #à chaque tour de boucle on prend une lettre de "coucou" et une lettre de "colibri"
    print(u+v)

"""
Explanation: Les boucles
End of explanation
"""


b = "Je m'appelle {}."
print(b)
print(b.format("Mathieu"))

print(a.format("Mathieu"))

b = "My name is {1}, {0} {1}."
print(b.format("James", "Bond"))

b2 = "My name is {nom}, {prenom} {nom}."
print(b2.format(prenom="James", nom="Bond"))

c = "Veuillez charger le fichier acquisition_t{:03d}.txt" #nombre décimal sur 3 chiffres, éventuellement complétés de zéros
print(c.format(5))
print(c.format(23))
print(c.format(328))

print(c.format(0.1))
print(c.format("hi"))

"""
Explanation: Phrases à trous
End of explanation
"""


c.format?

print("Veuillez charger le fichier acquisition_t%03d.txt"%5)

"""
Explanation: Syntaxe complète des instructions de formattage, si un jour vous avez envie d'afficher un nombre hexadécimal sur 7 charactères minimum, éventuellement complété avec des symboles livre sterling, ou un nombre flottant avec 2 chiffres significatifs.
On peut aussi obtenir de l'aide sur une méthode d'un objet.
End of explanation
"""


l = [a, b, 127, 3.14, ["James", "Bond"], c]
print(l)
print(l[0])
print(l[0][1])
print(l[0]+l[1].format(l[-2][0], l[-2][1])) # pour "déplier" tous les éléments de la liste l[-2] en tant qu'arguments de la fonction format
#possible d'écrire directement format(*l[-2])
print(l[-1].format(l[2]) + " Mr {}.".format(l[-2][-1]))

"""
Explanation: Listes
End of explanation
"""


l[2] = 12
l[-2][-1] = 3
print(l[-1].format(l[2]) + " Mr {}.".format(l[-2][-1]))

l2 = []
for i in range(3):
    l2.append(i**2)
print(l2)

"""
Explanation: Il est possible de modifier les éléments d'une liste et même de changer leur type.
End of explanation
"""


t = (a, b, 127, 3.14, ("James", "Bond"), c)
print(t)
print(t[0])
print(t[0][1])
print(t[0]+t[1].format(*t[-2]))
print(t[-1].format(t[2]) + " Mr {}.".format(t[-2][-1]))

t[2] = 12

tuple(l)

list(t)

"""
Explanation: tuple
Comme une liste, mais avec des parenthèses au lieu de crochets. Il est interdit de modifier le contenu d'un tuple.
End of explanation
"""


import os
os.listdir()

"""
Explanation: Librairies
Import
Toute la librairie
End of explanation
"""


from os import listdir
listdir()

"""
Explanation: Une seule fonction dans la librairie, directement accessible sans avoir à taper librairie.fonction
End of explanation
"""


from os import path #sous-librairie de os
print(path.isfile('Initiation.ipynb'))
from os.path import isfile
print(isfile('Initiation.ipynb'))

"""
Explanation: Marche aussi avec les sous-librairies et les fonctions des sous librairies.
End of explanation
"""


import numpy as np #abbréviation du nom de la librairie pour taper 2 lettres au lieu de 5

"""
Explanation: La syntaxe maléfique de l'import de tout ce qui est dans une librairie.
python
from os import *
Numpy: tableaux numériques
End of explanation
"""


np.zeros(3), np.ones(2, complex), np.arange(4)

l = [1,5,7] #liste numérique
print(l)
a = np.array(l) #transformée en tableau numpy
print(a)
b = np.array([1.2, 5, 6]) #les 2 étapes d'un coup
print(b)
print("a est un tableau à {} dimensions de taille {} contenant uniquement des {}".format(a.ndim, a.shape, a.dtype)) 
print("b est un tableau à {} dimensions de taille {} contenant uniquement des {}".format(b.ndim, b.shape, b.dtype)) 

"""
Explanation: Quelques fonctions pour créer des tableaux standards.
End of explanation
"""


print(2 * a)
print(a + b)
print(a * b)
print(a / b)
print(a>2)
print(np.exp(a))

"""
Explanation: Toutes les opérations se font élément par élément, même la multiplication. Pas besoin de point comme en MATLAB. La multiplication matricielle se fait avec np.matmul.
End of explanation
"""


c = a + b
print(c.dtype)
d = np.array([1,2,3])/a #division réélle, bseoin de passer en flottant, même si les tableaux ne contiennent que des entiers
print(d)
print(d.dtype)
e = np.array([1,2,3])//a #division Euclidienne, on reste en entiers
print(e)
print(e.dtype)

"""
Explanation: Le type des tableaux s'adapte automatiquement si besoin
End of explanation
"""


a = np.array([[1,2,3],[7,4,5]])
print("a est un tableau à {} dimensions de taille {} contenant uniquement des {}".format(a.ndim, a.shape, a.dtype)) 

print(a)
print(a.T)

"""
Explanation: Tableaux en 2 ou plus dimensions en imbriquant des listes
End of explanation
"""


print(a[0,1])
print(a[0])
print(a[0][1])
print(a[:,0])
print(a[::-1,[0, 2]])
print(a[a>2])

"""
Explanation: De nombreuses possibilités d'indexation
End of explanation
"""


print(a)
print(b)
print(a.shape, b.shape)
a + b

a.T + b

print(a.sum())
print(a.sum(axis=0))
print(a.sum(axis=1))

"""
Explanation: Possible de faire des opération si l'un des tableaux est de dimension plus faible et si la forme de celui-ci correspond à la fin de la forme de l'autre tableau.
End of explanation
"""


from matplotlib import pylab as plt
#permet la modification en live des figures dans le notebook
%matplotlib

plt.plot(b)

"""
Explanation: Matplotlib
Graphiques, lecture et écriture d'images
~~C'est sûrement la seule fois où je recommande un import *.~~
End of explanation
"""


%matplotlib inline
plt.plot(b)

"""
Explanation: Pour un document à montrer, on préfère avoir des figures directement insérée dedans en tant qu'image.
End of explanation
"""


%matplotlib

plt.figure('Evolution de b') # création ou sélection d'une figure. La figure est nommée, ce qui est plus explicite qu'une numérotation
plt.clf() # on efface la figure courante
plt.plot(b)
plt.yscale('log')
plt.ylabel('b')
plt.xlabel(r'$\gamma_c$') # pas de caractères spéciaux, donc on a le droit de mettre des antislash pour les commandes LaTeX
plt.savefig('mafig.pdf')

print('a\tb')

"""
Explanation: Mais on ne peut plus sélectionner les données directement, pas très pratique pour l'analyse de données. On revient donc en mode normal (fenêtre externe).
End of explanation
"""


