{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "eddab7fb",
   "metadata": {},
   "source": [
    "# Traitement du Signal - TDM1 : NumPy\n",
    "\n",
    "---\n",
    "**AVANT DE COMMENCER, TRES IMPORTANT !!**\n",
    "\n",
    "Durant ce semestre, vous aurez des TDM à rendre.\n",
    "\n",
    "Vous aurez donc dans ces fichiers de TDM des cellules de codes à compléter, comme celle-ci :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8ef86337",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcc17021",
   "metadata": {},
   "source": [
    "Ou des cellules texte à compléter (commençant par **_REPONSE_**) :"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5205e23",
   "metadata": {},
   "source": [
    "**_REPONSE :_** _Ici, vous écrivez votre réponse._"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "687f90de",
   "metadata": {},
   "source": [
    "Vérifiez bien avant de rendre un TDM que toutes les cellules (codes et texte) soient bien **complétées**."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21b868af",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "L'objectif de ce premier TDM va être de prendre en main le package python NumPy. Cette librairie sert à manipuler efficacement des tableaux de données, contenant des entiers, des nombres décimaux (float), des nombres complexes (complex), ou autre. De plus ces données peuvent être codées différement (mais on verra ça plus tard). On peut manipuler des tableaux à plusieurs dimensions, mais dans le contexte de ce cours, on utilisera uniquement des tableaux à une seule dimension (ce qui représente un signal). De ce fait, on peut se poser une question: pourquoi ne pas utiliser une liste Python pour manipuler les signaux ? A travers ce TDM, nous répondrons donc à cette question.\n",
    "\n",
    "Cette librairie est incontournable dans le domaine et va être utilisée durant tout le semestre, donc prenez bien le temps de lire la documentation : https://numpy.org/doc/2.3/user/index.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9eabb79",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import de la librairie NumPy\n",
    "import numpy as np\n",
    "\n",
    "# Import de la librairie time, qui permettra de mesurer le temps d'exécution de certaines commandes\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0792d760",
   "metadata": {},
   "source": [
    "Lorsque vous utiliszz une fonction NumPy, je vous invite fortement à aller lire la documentation officielle de NumPu, comme précisé dessus, mais vous pouvez également utiliser la fonction *help* afin d'avoir la documentation directement dans votre Notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e476e16",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exemple de documentation pour la fonction print\n",
    "help(print)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81ea5a9e",
   "metadata": {},
   "source": [
    "\n",
    "Je vous recommande **FORTEMENT** :\n",
    "- de prendre des notes durant ce TDM sur les fonctions NumPy vues, afin de créer un document qui vous sera utile durant tout le semestre : une cheat sheet\n",
    "- de vous partager le clavier si vous êtes en binôme ! Il faut que tout le monde code !\n",
    "- de ne pas utiliser d'IA pour faire le TDM à votre place (ChatGPT, Gemini, Claude, ou encore pire, Grok...). Vous aurez un examen pratique en fin de semestre, sans possibilité de les consulter, donc autant apprendre en TDM\n",
    "\n",
    "Ce TDM va être répétitif: pour chaque exercice, je vous demande de le réaliser avec:\n",
    "- un tableau sous forme de liste Python (ex: $[1, 2, 3, 4]$)\n",
    "- un tableau NumPy (ex: $np.array([1, 2, 3, 4])$)\n",
    "\n",
    "A travers les différents exercices, vous vous rendrez compte normalement que même si vous maîtrisez bien les listes Python (enfin, vous croyez bien les maîtriser...), un tableau NumPy est très souvent beaucoup plus optimisé, en terme d'efficacité, de temps d'exécution, et de lisibilité de code !\n",
    "\n",
    "De ce fait, avant de partir la tête dans le guidon afin de finir le TDM au plus vite, lisez la documentation pour trouver la fonction la plus adaptée (oui, je le répète une nouvelle fois, afin d'être sûr que vous avez bien capté le message). Très souvent, une ou deux lignes de code suffisent pour les tableaux NumPy !"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b50b4fac",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 1 : La base de la base de NumPy\n",
    "\n",
    "### De la liste au tableau\n",
    "\n",
    "Commençons tout d'abord par créer un tableau NumPy. Etant donné qu'une liste est un tableau d'une seule dimension, on peut d'abord créer un tableau à partir d'une liste python."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a71fd14",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Une première liste Python\n",
    "L = [2, 5, 1, 8, 3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50ecac58",
   "metadata": {},
   "source": [
    "Convertissez la liste $L$ précédemment créée, en un tableau NumPy affectée à la variable $T$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0a5d6db",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Conversion de la liste L en un tableau Numpy T\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a283ff41",
   "metadata": {},
   "source": [
    "Affichez maintenant le type de données de $T$ (pour vérifier que c'est bien un tableau NumPy), ainsi que le type de données de ces éléments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "075eadbc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage du type de données de T et du type de données de ces éléments\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e650a98a",
   "metadata": {},
   "source": [
    "En effet, contrairement à une liste, qui peut inclure n'importe quel type de données (en réalité, les éléments de la liste sont des pointeurs vers des objets Python), les éléments d'un tableau NumPy ont un type de données. Ici, vous devriez avoir un type de données *int64*, à savoir des entiers 64 bits. Cela veut dire que si vous ajoutez un élément qui ne convient pas au type de données prévu, le type de données de tous les éléments du tableau changera. \n",
    "\n",
    "Pour illustrer ces précédentes lignes, répétez les mêmes opérations avec les listes $L_2$, $L_3$, et $L_4$. Convertissez les listes en tableaux NumPy, et affichez le type de données des éléments des tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "790f6fa1",
   "metadata": {},
   "outputs": [],
   "source": [
    "L2 = [2, 5, 1, 8, 3, 7.5]\n",
    "L3 = [2, 5, 1, 8, 3, 3j]\n",
    "L4 = [2, 5, 1, 8, 3, 'a']\n",
    "\n",
    "# A COMPLETER\n",
    "# Conversion des listes en tableaux et affichage des types de données des éléments des tableaux\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b344bcd",
   "metadata": {},
   "source": [
    "Affichez ensuite la taille de $T$, et son nombre de dimensions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d88b767e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la taille et du nombre de dimensions de T\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53825fdb",
   "metadata": {},
   "source": [
    "### Construction d'un tableau\n",
    "\n",
    "Même si on peut facilement convertir une liste en tableau, il est souvent préférable de construire le tableau directement avec NumPy. Pour cela, on va maintenant construire des tableaux, tout d'abord sous forme de liste Python, puis sous forme de tableau NumPy. \n",
    "\n",
    "**Attention: Je ne veux voir aucune conversion Liste -> Numpy et Numpy -> Liste, c'est tout l'intérêt de ce TDM !**\n",
    "\n",
    "Construisez tout d'abord un tableau nul (rempli de zéros), de taille 50"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f0641ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Construction d'un tableau nul de taille 50\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "787e8b37",
   "metadata": {},
   "source": [
    "Même exercice, mais avec un tableau de taille 10 000 000, remplis de uns. Et on va chronométrer tout ça."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c8b62118",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Construction d'un tableau remplis de uns, de taille 10 000 000\n",
    "\n",
    "# Avec une liste\n",
    "t_init = time.time()\n",
    "...\n",
    "t_end = time.time()\n",
    "print(f\"Construction de L: {t_end-t_init} s\")\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "t_init = time.time()\n",
    "...\n",
    "t_end = time.time()\n",
    "print(f\"Construction de T: {t_end-t_init} s\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "604c3b2b",
   "metadata": {},
   "source": [
    "Un nouveau tableau à construire: la suite des nombres allant de 0 à 149, donc de taille 150 ($A = [0, 1, 2, ..., 149]$)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f6bd2d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Construction du tableau représentant la suite allant de 0 à 149\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2620c9de",
   "metadata": {},
   "source": [
    "Construisez ensuite une liste et un tableau avec la suite des nombres allant de 1000 à 50, avec un pas de -10 ($B = [1000, 990, 980, ..., 50]$)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6dcf049a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Construction du tableau représentant la suite allant de 1000 à 50, avec un pas de -10\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61fde770",
   "metadata": {},
   "source": [
    "Pour finir, une dernière construction de liste et tableau contenant précisément 145 valeurs, allant de 68 à 1923, avec un pas régulier.\n",
    "\n",
    "*Note : Pour le tableau NumPy, il y a une fonction NumPy conçue précisément pour ce cas de problème, sans besoin de calculer le pas...*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "866f7e7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Construction du tableau de 145 valeurs, de 68 à 1923, avec un pas régulier\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab99f4f1",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 2 : Tableau + Elément = Tableau ?\n",
    "\n",
    "Pour cet exercice, je vous construis la liste et le tableau qu'on va utiliser. Et on va faire des opérations basiques dessus. Voilà..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a7c7b7d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# La liste et le tableau à manipuler pour ce nouvel exercice\n",
    "L = [2,5,8,3,9,1,7,45,3,69,2,8,7,66]\n",
    "T = np.array(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cfc06bf",
   "metadata": {},
   "source": [
    "Incrémentez de 2 chaque élement des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b42ce518",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Incrémentation de 2 de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7dd6cfff",
   "metadata": {},
   "source": [
    "Divisez maintenant tous les éléments des listes/tableaux par 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "74762a4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Division par 5 de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62bbf5c6",
   "metadata": {},
   "source": [
    "Calculez maintenant la racine carrée de tous les éléments des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "30c52c14",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Racine carré des éléments de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5037164d",
   "metadata": {},
   "source": [
    "Pour finir, calculez la valeur absolue de tous les éléments des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98e955b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Valeur absolue des éléments de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e880170d",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 3 : Extraire et combiner\n",
    "\n",
    "Durant le semestre, on va beaucoup manipuler des signaux... Rien de très étonnant... Dans cette manipulation, il est possible qu'on ait besoin de :\n",
    "- Récupérer un extrait d'un signal, une partie\n",
    "- Concaténer plusieurs signaux pour en faire un grand signal\n",
    "\n",
    "Avec cet exercice, on va découvrir comment faire ces opérations efficacement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b289bf10",
   "metadata": {},
   "outputs": [],
   "source": [
    "# La liste et le tableau à manipuler pour ce nouvel exercice\n",
    "L = [2,5,8,3,9,1,7,45,3,69,2,8,7,66]\n",
    "T = np.array(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c445836a",
   "metadata": {},
   "source": [
    "Affichez le premier élément des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e31d2f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la première valeur de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f83efaef",
   "metadata": {},
   "source": [
    "Même question, mais avec le dernier élément"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae08aa30",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la dernière valeur de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d70181dc",
   "metadata": {},
   "source": [
    "Récupérez et affichez ensuite les éléments des listes/tableaux entre les positions 5 et 9 incluses (ce qui donnera $[9,1,7,45,3]$)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "712b7505",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage des éléments entre les positions 5 et 9 incluses de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b849400",
   "metadata": {},
   "source": [
    "Affichez maintenant un élément sur deux des listes/tableaux (index 0, 2, 4, etc.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09d8f969",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage d'un élément sur deux de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7a68e2e",
   "metadata": {},
   "source": [
    "**ATTENTION :** Lorsque vous extrayez un sous-tableau NumPy, vous faites en réalité une vue du tableau, et non une copie modifiée. Cela veut dire que si vous modifiez le sous-tableau en question, vous modifiez également le tableau original. Un exemple ci-dessous:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "498dd684",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exemple de modification de vue d'un tableau NumPy\n",
    "\n",
    "tab = np.array([1,2,3,4,5,6])\n",
    "sub_tab = tab[1:4]\n",
    "print(f\"Tableau tab : {tab}\")\n",
    "print(f\"Sous-tableau sub_tab : {sub_tab}\")\n",
    "\n",
    "sub_tab[1] = 10000000 # On modifie une valeur du sous-tableau\n",
    "print(f\"Sous-tableau sub_tab après modification : {sub_tab}\")\n",
    "print(f\"Tableau tab après modification : {tab}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6e848a0",
   "metadata": {},
   "source": [
    "Recopiez le code ci-dessous et modifiez la ligne d'extraction (*sub_tab = tab[1:4]*) afin que la modification de *sub_tab* n'entraîne pas la modification de *tab*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d2a3706",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Modification du sous-tableau sans modifier le tableau original\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7724eb41",
   "metadata": {},
   "source": [
    "Créez ensuite les liste et tableau $L_{inv}$ et $T_{inv}$, à savoir les liste et tableau $L$ et $T$ mais à l'envers\n",
    "\n",
    "*Note : vous pouvez réaliser ces opérations avec de l'indexation, comme précédemment, ou alors pour le tableau NumPy avec une fonction spécifique*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0fd83619",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER   \n",
    "# Inversion de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19a2ff11",
   "metadata": {},
   "source": [
    "On rajoute maintenant des listes/tableaux pour la suite"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d2941af",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Chouette, de nouveaux éléments !\n",
    "\n",
    "L2 = [4,9,63,5,7,88,7,4,1]\n",
    "T2 = np.array(L2)\n",
    "\n",
    "L3 = [96,97,98,99]\n",
    "T3 = np.array(L3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b441d0d",
   "metadata": {},
   "source": [
    "Concaténez les listes/tableaux $L$ et $L_2$, puis $T$ et $T_2$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c7b83773",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Concaténation de L et L2, et T et T2\n",
    "\n",
    "# Avec L et L2\n",
    "...\n",
    "\n",
    "# Avec T et T2\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0578afaf",
   "metadata": {},
   "source": [
    "Pour finir, concaténez les listes/tableaux $L$, $L_2$ et $L_3$, puis $T$, $T_2$ et $T_3$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9f61dc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Concaténation de L, L2, L3 ; puis T, T2, T3\n",
    "\n",
    "# Avec L, L2, L3\n",
    "...\n",
    "\n",
    "# Avec T, T2, T3\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f9d4ad0",
   "metadata": {},
   "source": [
    "**Note importante :** Il se peut ici que vous ayez utilisé la fonction *np.append*. Je ne dis pas que ce que vous avez fait n'est pas correct, mais cela montre en partie que vous utilisez alors un tableau NumPy comme une liste, alors que ce n'est vraiment pas la mentalité recherchée. \n",
    "\n",
    "Alors pourquoi ce n'est pas bien ? \n",
    "- Lorsque vous ajoutez un élément dans une liste avec la fonction *append*, la liste s'aggrandit avec un nouveau pointeur, mais l'objet reste le même.\n",
    "- Lorsque vous ajoutez un élément dans un tableau NumPy, vous construisez en réalité un nouveau tableau NumPy, car les **tableaux ont une taille fixe**. \n",
    "\n",
    "De ce fait, si vous avez plusieurs éléments à ajouter à un tableau, mieux vaut faire une liste, convertir en tableau NumPy, et concaténer au tableau original, ou alors trouver la bonne fonction NumPy qui permet de créer le bon tableau à ajouter. Mais je ne veux pas voir une multitude d'appels de la fonction *np.append*."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b53e7d1d",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 4 : Elle est où la valeur, elle est où ?\n",
    "\n",
    "Sur nos signaux (donc tableaux), nous aurons besoin également d'extraire de l'information utile, comme par exemple la valeur maximum, mais également la position où elle se situe. Ici, on va voir ensemble quelques fonctionnalités utiles de NumPy qui vont dans ce sens."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f355ac62",
   "metadata": {},
   "outputs": [],
   "source": [
    "# La liste et le tableau à manipuler pour ce nouvel exercice\n",
    "L = [20,5,9,7,8,66,3,14,5,32,8,77]\n",
    "T = np.array(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba842958",
   "metadata": {},
   "source": [
    "Affichez la valeur maximale des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d746d5b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la valeur maximale de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0e16fce",
   "metadata": {},
   "source": [
    "Affichez maintenant **la position** de la valeur maximale des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb5fcf79",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la position de la valeur maximale de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e828ffb8",
   "metadata": {},
   "source": [
    "On va répéter la même opération cette fois, mais avec une liste et tableau beaucoup plus gros (10 000 000 de valeurs), et chronométrer la recherche"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c4d1789",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la position de la valeur maximale de L et T\n",
    "\n",
    "T_big = np.random.randint(0,15000,(10000000))\n",
    "L_big = T_big.tolist()\n",
    "\n",
    "# Avec la liste L_big\n",
    "t_init = time.time()\n",
    "...\n",
    "t_end = time.time()\n",
    "print(f\"Affichage de la position de la valeur max de L_big (non optimisé): {t_end-t_init} s\")\n",
    "\n",
    "# Avec le tableau NumPy T_big\n",
    "t_init = time.time()\n",
    "...\n",
    "t_end = time.time()\n",
    "print(f\"Affichage de la position de la valeur max de T: {t_end-t_init} s\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15126ae7",
   "metadata": {},
   "source": [
    "On peut reprendre nos listes et tableaux $L$ et $T$ pour la suite :D\n",
    "\n",
    "Retrouvez maintenant les indices des valeurs strictement supérieures à 10 dans nos listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "73fd8d2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Affichage de la position desvaleurs supérieures à 10 de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b1f3a0e",
   "metadata": {},
   "source": [
    "*Note : Comme vous avez pu le remarquer, si vous avez bien utilisé la fonction np.argwhere, le retour de la fonction n'est pas un tableau, mais une liste de tableau. Ici, la liste ne comprend qu'un tableau, car le tableau original analysé n'a qu'une seule dimension. Si vous utilisez la fonction pour analyser un tableau à N dimensions, vous aurez une liste de N tableaux*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84c27792",
   "metadata": {},
   "source": [
    "Pour finir cet exercice, recensez toutes les valeurs différentes des listes/tableaux.\n",
    "\n",
    "*ex: pour la listes [1,2,1], les valeurs différentes à retrouver sont [1,2]*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5548833",
   "metadata": {},
   "outputs": [],
   "source": [
    "T = np.random.randint(0, 100, (75))\n",
    "L = T.tolist()\n",
    "\n",
    "# A COMPLETER\n",
    "# Récupération des valeurs différentes des listes/tableaux\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8488c520",
   "metadata": {},
   "source": [
    "Refaites la même opération, mais en récupérant également le nombre d'occurences de chaque valeur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e2af89e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Récupération des valeurs différentes des listes/tableaux, ainsi que leur nombre d'occurences\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "891f9541",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 5 : Tableau + Tableau = Tableau ?\n",
    "\n",
    "Un signal, c'est modifiable, c'est tout l'intérêt de cet EC. De ce fait, on va être amené à faire des calculs entre plusieurs signaux."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0217d8ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Les listes et tableaux à manipuler pour ce nouvel exercice\n",
    "T1 = np.random.randint(0,10,(25))\n",
    "T2 = np.random.randint(0,10,(25))\n",
    "L1 = T1.tolist()\n",
    "L2 = T2.tolist()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ffb41fe",
   "metadata": {},
   "source": [
    "Calculez la somme des éléments des listes/tableaux (donc par exemple, la somme de tous les éléments de $L_1$, qui donnera en sortie un scalaire)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3cfa12ae",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Somme des éléments L1 et T1\n",
    "\n",
    "# Avec L1\n",
    "...\n",
    "\n",
    "# Avec T1\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a76fbb59",
   "metadata": {},
   "source": [
    "Calculez maintenant la moyenne des listes/tableaux"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89b9d4e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Moyenne de L1 et T1\n",
    "\n",
    "# Avec L1\n",
    "...\n",
    "\n",
    "# Avec T1\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f87989a",
   "metadata": {},
   "source": [
    "Plus complexe: passons au produit scalaire de deux vecteurs. Effectuez le produit scalaire sur deux vecteurs identiques (liste ou tableau)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8772ba61",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Produit scalaire entre L1 et L1, puis T1 et T1\n",
    "\n",
    "# Avec L1 et L1\n",
    "...\n",
    "\n",
    "# Avec T1 et T1\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb3d513b",
   "metadata": {},
   "source": [
    "Répétez l'opération, mais avec 2 vecteurs différents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7fc89b38",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Produit scalaire entre L1 et L2, puis T1 et T2\n",
    "\n",
    "# Avec L1 et L2\n",
    "...\n",
    "\n",
    "# Avec T1 et T2\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c0ed06d",
   "metadata": {},
   "source": [
    "Faites la multiplication des 2 listes $L_1$ et $L_2$, élément par élément, puis avec les tableaux $T_1$ et $T_2$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "165bd7c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Multiplication élément par élément entre L1 et L2, puis T1 et T2\n",
    "\n",
    "# Avec L1 et L2\n",
    "...\n",
    "\n",
    "# Avec T1 et T2\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6b3391a",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 6 : Opérations logiques\n",
    "\n",
    "Les modifications, c'est bien, mais c'est mieux si on peut choisir les éléments qu'on souhaite modifier, donc effectuer des modifications conditionnelles. Cela permet d'éviter d'écrire des *if, else*, et donc de gagner en clarté de code.\n",
    "\n",
    "Avant de faire ces modifications conditionnelles, il nous faut d'abord créer ce qu'on appelle des masques, à savoir des listes/tableaux de même dimensions que ceux étudiés, mais contenant uniquement des booléens (*True* ou *False*). Chaque élément du masque associé au tableau indique donc si la condition étudiée est validée par l'élement du tableau."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bae24725",
   "metadata": {},
   "outputs": [],
   "source": [
    "# La liste et le tableau à manipuler pour ce nouvel exercice\n",
    "L = [20,5,9,7,8,66,3,14,5,32,8,77]\n",
    "T = np.array(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "595a05df",
   "metadata": {},
   "source": [
    "Créez un vecteur indiquant pour chaque valeur du vecteur original (L et T) si elle est supérieure strictement à 10\n",
    "\n",
    "*Par exemple, si $L = [5, 20, 9, 10, 67]$, le vecteur créé sera $L\\_sup\\_10 = [False, True, False, False, True]$*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56567915",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Création du vecteur indiquant toutes les valeurs de L,T supérieures strictement à 10\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e6491cc",
   "metadata": {},
   "source": [
    "Répétez la même opération, mais indiquant pour chaque valeur du vecteur original si elle est inférieure ou égale à 15"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d1e1a84e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Création du vecteur indiquant toutes les valeurs de L,T inférieures ou égales à 10\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b6bab37",
   "metadata": {},
   "source": [
    "Construisez le vecteur indiquant pour chaque valeur du vecteur original si elle est supérieure ou égale à 20, ou égale à 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bea090b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Création du vecteur indiquant toutes les valeurs de L,T supérieures ou égales à 20 ou égales à 5\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50d48581",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Ex 7 : Modifier un vecteur conditionnellement\n",
    "\n",
    "Bon, c'est cool les masques, mais ça ne sert pas vraiment à grand chose si on n'en fait rien. On peut maintenant s'attaquer aux modifications conditionnelles. Les tableaux, associés à leurs masques, peuvent alors être modifiés partiellement (à savoir uniquement les valeurs qui remplissent ou non la condition étudiée).\n",
    "\n",
    "Avant d'utiliser les masques, on va voir quelques fonctions utiles de NumPy qui calculent elles-mêmes le masque à utiliser."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "189ed7be",
   "metadata": {},
   "outputs": [],
   "source": [
    "# La liste et le tableau à manipuler pour ce nouvel exercice\n",
    "T = np.random.rand(20)*20\n",
    "L = T.tolist()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3409f020",
   "metadata": {},
   "source": [
    "Modifiez les listes/tableaux pour limiter les valeurs entre 5 et 15\n",
    "\n",
    "*(c'est-à-dire que toutes les valeurs en-dessous de 5 passent à 5, et toutes les valeurs au-dessus de 15 passent à 15)*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "61db505b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Limitation des valeurs de L et T entre 10 et 15\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29034193",
   "metadata": {},
   "source": [
    "Arrondissez maintenant les valeurs des listes/tableaux à l'entier le plus proche"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3424e734",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Arrondi des valeurs de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35cf08a1",
   "metadata": {},
   "source": [
    "Répétez la même opération, mais en arrondissant:\n",
    "- à la valeur entière plancher\n",
    "- à la valeur entière plafond"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7e5d00da",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Arrondi des valeurs de L et T à la valeur entière plancher\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7e34689",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Arrondi des valeurs de L et Tn à la valeur entière plafond\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "625e9b70",
   "metadata": {},
   "source": [
    "Dernière étape, plus complexe avec des nouveaux vecteurs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2233837f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Les nouveaux vecteurs\n",
    "L = list(range(20))\n",
    "T = np.array(L)\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e519611e",
   "metadata": {},
   "source": [
    "Modifiez les vecteurs pour que toutes les valeurs paires soient égales à -1. Les valeurs impaires resteront inchangées.\n",
    "\n",
    "*Indice : pour NumPy, je vous invite à voir la documentation de la fonction np.where*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b57551fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A COMPLETER\n",
    "# Modification des valeurs paires (passage à -1) de L et T\n",
    "\n",
    "# Avec une liste\n",
    "...\n",
    "\n",
    "# Avec un tableau NumPy\n",
    "..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16438566",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Pour finir ce TDM, je vous invite donc, si ce n'est pas fait, **à noter de côté** les différentes fonctions NumPy que vous avez utilisé, sur une feuille ou un éditeur de texte. A vous ensuite, durant les prochaines semaines, d'utiliser les différentes fonctions vues aujourd'hui afin de coder efficacement.\n",
    "\n",
    "*De plus, comme vous avez pu le voir, c'est souvent plus rapide à écrire en 1/2 lignes, donc ça veut dire que vous finissez les TDM plus tôt ;)*"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "deep",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
