{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Börja plotta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "x = np.linspace(-5, 5, 100)\n",
    "y = x**2\n",
    "\n",
    "plt.plot(x, y, '-')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Spara figur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(x, y, '-')\n",
    "plt.savefig('figur.pdf', dpi=300)  # pdf och andra vektor/bitmap-format funkar också"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Justera utseende efter behov"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "plt.style.use('dark_background')\n",
    "plt.plot(x, y, linewidth=1, color='white')\n",
    "plt.plot(x, y, '*', linewidth=2, color='red')\n",
    "\n",
    "\n",
    "plt.title(r'Funktionen $y = x^2$')\n",
    "plt.xlabel('x-axeln')\n",
    "plt.ylabel('y-axeln')\n",
    "plt.grid(True, color='gray') \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Finslipa typsnitt på text/ekvationer (LaTeX)\n",
    "Kräver fungerande LaTeX-installation, dock!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.style.use('default')\n",
    "plt.rcParams['text.usetex'] = True\n",
    "plt.rcParams['font.family'] = 'serif'\n",
    "\n",
    "plt.plot(x, y, linewidth=2, linestyle='-', color='black')\n",
    "plt.title(r'Funktionen $y = x^2$', fontsize=20)\n",
    "plt.xlabel(r'$x$-axeln', fontsize=18)\n",
    "plt.ylabel(r'$y$-axeln', fontsize=18)\n",
    "plt.xticks(fontsize=16)  # Justera storlek på x-ticks\n",
    "plt.yticks(fontsize=16)  # Justera storlek på y-ticks\n",
    "plt.grid(True, color='gray', linewidth=.3) \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mer justeringar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.rcParams['text.usetex'] = True\n",
    "plt.rcParams['font.family'] = 'serif'\n",
    "plt.rcParams['axes.facecolor'] = 'whitesmoke'  # Bakgrund på plotområdet\n",
    "plt.rcParams['figure.facecolor'] = 'lightgray'  # Bakgrund på hela figuren\n",
    "\n",
    "plt.plot(x, y, linewidth=2, linestyle='-', color='black')\n",
    "plt.title(r'Funktionen $y = x^2$', fontsize=20)\n",
    "plt.xlabel(r'$x$-axeln', fontsize=18)\n",
    "plt.ylabel(r'$y$-axeln', fontsize=18)\n",
    "plt.xticks(fontsize=16) \n",
    "plt.yticks(fontsize=16) \n",
    "plt.grid(True, color='gray', linewidth=.3) \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sätt färgkod efter önskemål (företags-specifikt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.rcParams['text.usetex'] = True\n",
    "plt.rcParams['font.family'] = 'serif'\n",
    "\n",
    "# Eller med RGB-koder\n",
    "plt.gca().set_facecolor((0.4, 0.5, 0.8))  # Ljusgrå bakgrund\n",
    "\n",
    "plt.plot(x, y, linewidth=2, linestyle='-', color='black')\n",
    "plt.title(r'Funktionen $y = x^2$', fontsize=20)\n",
    "plt.xlabel(r'$x$-axeln', fontsize=18)\n",
    "plt.ylabel(r'$y$-axeln', fontsize=18)\n",
    "plt.xticks(fontsize=16)  # Justera storlek på x-ticks\n",
    "plt.yticks(fontsize=16)  # Justera storlek på y-ticks\n",
    "plt.grid(True, color='black', linewidth=.3) \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Skapa bild av matris"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "nn = 1000\n",
    "matrix = np.zeros((nn, nn))\n",
    "sigma = 5000\n",
    "\n",
    "for ii in range(nn):\n",
    "    for jj in range(nn):\n",
    "        matrix[ii,jj] = .2 * np.random.rand() + np.sin(-((ii-nn/2)**2 + (jj-nn/2)**2)/sigma)\n",
    "\n",
    "plt.imshow(matrix)\n",
    "plt.title('Matrisplot')\n",
    "plt.colorbar()\n",
    "plt.savefig('matrix.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(matrix[:,int(nn/2)])\n",
    "plt.title('Plotta tvärsnitt av matris')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Litet sidospår - skapa matris utan for-loopar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "nn = 1000\n",
    "matrix = np.zeros((nn, nn))\n",
    "sigma = 5000\n",
    "\n",
    "t1 = time.time()\n",
    "for ii in range(nn):\n",
    "    for jj in range(nn):\n",
    "        matrix[ii,jj] = .2*np.random.rand() + np.sin(-((ii-nn/2)**2 + (jj-nn/2)**2)/sigma)\n",
    "t2 = time.time()\n",
    "print(f'Med for-loopar: {round(t2 - t1,3)} s')\n",
    "\n",
    "# Skapa denna matris utan for-loopar\n",
    "ii, jj = np.meshgrid(np.arange(nn), np.arange(nn))\n",
    "dist_squared = (ii - nn / 2)**2 + (jj - nn / 2)**2\n",
    "matrix = 0.2 * np.random.rand(nn, nn) + np.sin(-dist_squared / sigma)\n",
    "t3 = time.time()\n",
    "print(f'Utan for-loopar: {round(t3 - t2,3)} s')\n",
    "print(f'\\n Sistnämnda är ca {round((t2 - t1) / (t3 - t2))} ggr snabbare')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tidsåtgång - olika matematiska operationer\n",
    "\n",
    "$$\n",
    "\\begin{aligned}\n",
    "1.\\quad & f(x) = x \\\\\n",
    "2.\\quad & f(x) = x^2 \\\\\n",
    "3.\\quad & f(x) = \\sin(x) \\\\\n",
    "4.\\quad & f(x) = \\sin(x^2) \\\\\n",
    "5.\\quad & f(x) = \\mathrm{e}^{-x^2/100}\\sin(x^2)\n",
    "\\end{aligned}\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "nn = 10**7\n",
    "\n",
    "# 1.\n",
    "t1 = time.time()\n",
    "tmp = [ii for ii in range(nn)]\n",
    "print(time.time() - t1)\n",
    "\n",
    "# 2.\n",
    "t1 = time.time()\n",
    "tmp = [ii**2 for ii in range(nn)]\n",
    "print(time.time() - t1)\n",
    "\n",
    "# 3.\n",
    "t1 = time.time()\n",
    "tmp = [np.sin(ii) for ii in range(nn)]\n",
    "print(time.time() - t1)\n",
    "\n",
    "# 4.\n",
    "t1 = time.time()\n",
    "tmp = [np.sin(ii**2) for ii in range(nn)]\n",
    "print(time.time() - t1)\n",
    "\n",
    "# 5.\n",
    "t1 = time.time()\n",
    "tmp = [np.exp(-ii**2/100)*np.sin(ii**2) for ii in range(nn)]\n",
    "print(time.time() - t1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# \"Riktig\" heatmap (demo, enkel fysikalisk simulering)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Parametrar\n",
    "size = 100  # Matrisens (\"rummets\") storlek i pixlar\n",
    "alpha = 1.8  # Värmeledningskoefficient\n",
    "time_steps = 1500  # Antal tidssteg\n",
    "dt = 0.1  # Tidssteg (inkrement)\n",
    "dx = 1.0  # Gitteravstånd\n",
    "\n",
    "# Initial temperaturfördelning (värme längs vissa kantr)\n",
    "T = np.ones((size, size))*20  # temp i rum = 20 grader\n",
    "\n",
    "T[20:40, 0] = 0  \n",
    "T[0, 30:60] = 0  \n",
    "T[10:80, size - 1] = 0  \n",
    "\n",
    "# Funktion för värmeledning\n",
    "def heat_equation(T, alpha, dt, dx):\n",
    "    T_new = T.copy()\n",
    "    for i in range(1, T.shape[0] - 1):\n",
    "        for j in range(1, T.shape[1] - 1):\n",
    "            T_new[i, j] = T[i, j] + alpha * dt / dx**2 * (\n",
    "                T[i+1, j] + T[i-1, j] + T[i, j+1] + T[i, j-1] - 4*T[i, j]\n",
    "            )\n",
    "    return T_new\n",
    "\n",
    "# Värmespridning efter viss tid\n",
    "for t in range(time_steps):\n",
    "    T = heat_equation(T, alpha, dt, dx)\n",
    "\n",
    "plt.imshow(T, cmap='seismic', interpolation='gaussian') # gaussian -> \"jämna ut\" pixlar vid låg upplösning\n",
    "plt.colorbar()\n",
    "plt.title(f'Jämvikt i värmespridning (efter {time_steps} tidssteg)')\n",
    "plt.savefig('real_heatmap.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Samma heatmap, fast med konturlinjer (isobarer)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.imshow(T, cmap='seismic', interpolation='gaussian') # gaussian -> \"jämna ut\" pixlar vid låg upplösning\n",
    "plt.colorbar()\n",
    "contours = plt.contour(T, levels=10, cmap='coolwarm', linewidths=1)\n",
    "plt.clabel(contours, inline=True, fontsize=8)\n",
    "plt.title(f'Jämvikt i värmespridning (efter {time_steps} tidssteg)')\n",
    "plt.savefig('real_heatmap_contour.png', dpi=300)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# (Animering, värmeledning)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "frames_folder = 'frames_heat'\n",
    "if not os.path.exists(frames_folder):\n",
    "    os.makedirs(frames_folder)\n",
    "\n",
    "# Parametrar\n",
    "size = 100  # Matrisens storlek\n",
    "alpha = 1.8  # Värmeledningskoefficient\n",
    "total_steps = 1500  # Totalt antal tidssteg\n",
    "dt = 0.1  # Tidsinkrement\n",
    "dx = 1.0  # Gitteravstånd\n",
    "\n",
    "# Initial temperatur\n",
    "T = np.ones((size, size)) * 20  # Rumstemperatur = 20 grader\n",
    "T[20:40, 0] = 0  \n",
    "T[0, 30:60] = 0  \n",
    "T[10:80, size - 1] = 0\n",
    "\n",
    "# Funktion för ett tidssteg\n",
    "def heat_equation(T, alpha, dt, dx):\n",
    "    T_new = T.copy()\n",
    "    for i in range(1, T.shape[0] - 1):\n",
    "        for j in range(1, T.shape[1] - 1):\n",
    "            T_new[i, j] = T[i, j] + alpha * dt / dx**2 * (\n",
    "                T[i+1, j] + T[i-1, j] + T[i, j+1] + T[i, j-1] - 4*T[i, j]\n",
    "            )\n",
    "    return T_new\n",
    "\n",
    "# Simulering och lagra 15 jämnt fördelade snapshots\n",
    "heatmaps = []\n",
    "save_steps = np.linspace(0, total_steps-1, 15, dtype=int)\n",
    "\n",
    "for t in range(total_steps):\n",
    "    T = heat_equation(T, alpha, dt, dx)\n",
    "    if t in save_steps:\n",
    "        heatmaps.append(T.copy())\n",
    "\n",
    "# Rita och spara bilder\n",
    "for ii, T_snapshot in enumerate(heatmaps):    \n",
    "    plt.imshow(T_snapshot, cmap='seismic', interpolation='gaussian')\n",
    "    plt.colorbar()\n",
    "    contours = plt.contour(T_snapshot, levels=10, cmap='coolwarm', linewidths=1)\n",
    "    plt.clabel(contours, inline=True, fontsize=8)\n",
    "    \n",
    "    plt.title(f'Tid {ii+1}/{len(heatmaps)}')\n",
    "    plt.savefig(f'{frames_folder}/frame_{ii:04d}.png', dpi=300)\n",
    "    plt.clf()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3D-plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import cm\n",
    "\n",
    "X = np.arange(-15, 15, .025)\n",
    "Y = np.arange(-15, 15, .025)\n",
    "X, Y = np.meshgrid(X, Y)\n",
    "R = np.sqrt(X**2 + Y**2)\n",
    "Z = np.exp(-R**2/50)\n",
    "\n",
    "fig, ax = plt.subplots(subplot_kw= {\"projection\": \"3d\"})\n",
    "ax.plot_surface(X, Y, Z, vmin=Z.min(), cmap=cm.viridis)\n",
    "ax.set(xticklabels=[],\n",
    "       yticklabels=[],\n",
    "       zticklabels=[])\n",
    "\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Flera figurer i en mosaik"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy.ndimage import gaussian_filter\n",
    "from scipy.signal import savgol_filter\n",
    "import pywt\n",
    "\n",
    "# Generera brusig Gausskurva\n",
    "NN = 2000\n",
    "x = np.linspace(-5, 5, NN, endpoint=True)\n",
    "y = np.exp(-x**2) + .2 * np.random.rand(NN)\n",
    "\n",
    "# 1. Glidande medelvärde\n",
    "def moving_average(y, window_size=5):\n",
    "    return np.convolve(y, np.ones(window_size)/window_size, mode='same')\n",
    "y_ma = moving_average(y, window_size=10)\n",
    "\n",
    "# 2. Gaussisk utjämning\n",
    "y_gaussian = gaussian_filter(y, sigma=2)\n",
    "\n",
    "# 3. Savitzky-Golay-filter\n",
    "y_savgol = savgol_filter(y, window_length=11, polyorder=3)\n",
    "\n",
    "# 4. Fourier-filtrering\n",
    "Y = np.fft.fft(y)\n",
    "frequencies = np.fft.fftfreq(len(y), d=(x[1] - x[0]))\n",
    "cutoff = .5\n",
    "Y[np.abs(frequencies) > cutoff] = 0\n",
    "y_fourier = np.fft.ifft(Y).real\n",
    "\n",
    "# 5. Wavelet-denoising\n",
    "coeffs = pywt.wavedec(y, 'db4', level=3)\n",
    "coeffs[1:] = [pywt.threshold(c, np.std(c)/2, mode='soft') for c in coeffs[1:]]\n",
    "y_wavelet = pywt.waverec(coeffs, 'db4')[:NN]  # Anpassa längden om nödvändigt\n",
    "\n",
    "# Skapa 3x2 subplots\n",
    "fig, axes = plt.subplots(3, 2, figsize=(12, 9), constrained_layout=True)\n",
    "\n",
    "methods = [\n",
    "    (\"Original signal\", y),\n",
    "    (\"Moving Average\", y_ma),\n",
    "    (\"Gaussian Smoothing\", y_gaussian),\n",
    "    (\"Savitzky-Golay\", y_savgol),\n",
    "    (\"Fourier Filtering\", y_fourier),\n",
    "    (\"Wavelet Denoising\", y_wavelet)\n",
    "]\n",
    "\n",
    "for ax, (title, y_filtered) in zip(axes.flat, methods):\n",
    "    ax.plot(x, y, color='gray', alpha=0.5, label=\"Original (brusig)\")\n",
    "    ax.plot(x, y_filtered, color='r', label=\"Filtrerad\")\n",
    "    ax.set_title(title)\n",
    "    ax.legend()\n",
    "    ax.grid(True)\n",
    "\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Något om slumptalsgenerering (liten avstickare)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "n = int(1e8) # antal slumptal\n",
    "nbins = 60 # antal bins\n",
    "\n",
    "uniform_data = np.random.uniform(low=0.0, high=1.0, size=n)\n",
    "normal_data = np.random.normal(loc=0.5, scale=.15, size=n)\n",
    "\n",
    "plt.figure(figsize=(10, 5))\n",
    "\n",
    "plt.subplot(1, 2, 1)\n",
    "plt.hist(uniform_data, bins=nbins, color='skyblue', edgecolor='black')\n",
    "plt.title('Rektangelfördelning (uniform)')\n",
    "plt.xlabel('Värde')\n",
    "plt.ylabel('Frekvens')\n",
    "\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.hist(normal_data, bins=nbins, color='salmon', edgecolor='black')\n",
    "plt.title('Normalfördelning (gaussisk)')\n",
    "plt.xlabel('Värde')\n",
    "plt.ylabel('Frekvens')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Scatter-plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "#plt.style.use('dark_background')\n",
    "plt.style.use('bmh')\n",
    "\n",
    "# Två Gaussfördelade dataset\n",
    "np.random.seed(42)\n",
    "x1, y1 = np.random.normal(loc=0, scale=.7, size=(2, 500)) # loc = medelvärde, scale = standardavvikelse\n",
    "x2, y2 = np.random.normal(loc=3, scale=.3, size=(2, 500))\n",
    "\n",
    "plt.figure(figsize=(8, 8))\n",
    "plt.scatter(x1, y1, color='red', alpha=0.5, label='Fördelning 1', s=50) # alpha = genomskinlighet, s = cirkelstorlek\n",
    "plt.scatter(x2, y2, color='blue', alpha=0.5, label='Fördelning 2', s=50)\n",
    "\n",
    "# Anpassa plottens utseende\n",
    "plt.axhline(0, color='black', linewidth=0.2)\n",
    "plt.axvline(0, color='black', linewidth=0.2)\n",
    "plt.legend()\n",
    "plt.title('Scatterplot av två Gaussfördelningar')\n",
    "plt.xlabel('X')\n",
    "plt.ylabel('Y')\n",
    "plt.grid(True, linestyle='--', alpha=0.5)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cirkeldiagram"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "data = [1, 1, 1, 1, 2, 2, 3, 1, 1, 2, 3, 1, 1, 3, 1, 2, 3, 1, 2, 1]\n",
    "\n",
    "# Förekomster av varje värde\n",
    "labels = ['1', '2', '3']\n",
    "sizes = [data.count(1), data.count(2), data.count(3)]\n",
    "\n",
    "# Cirkeldiagram\n",
    "plt.figure(figsize=(6, 6))\n",
    "plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, colors=['darkred', 'darkgreen','gray'], textprops={'color': 'black'} )\n",
    "plt.title(\"Cirkeldiagram av datasetet\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ta ut data från Pandas DataFrame och gör figur"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import time\n",
    "\n",
    "t1 = time.time()\n",
    "df = pd.read_csv('../../1_numpy/codes/video_games_sales.csv')\n",
    "print(f'csv-fil importerad på {round(time.time() - t1, 4)} s')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "games_per_year = df['Year_of_Release'].value_counts().sort_index()\n",
    "#print(games_per_year)\n",
    "\n",
    "games_per_year.index = games_per_year.index.astype(int)\n",
    "print(games_per_year)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exempel på pandas-gränssnitt till Matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#plt.style.use('dark_background')\n",
    "games_per_year.plot(kind='bar', figsize=(10, 6), color='skyblue')\n",
    "\n",
    "# Lägg till etiketter och titel\n",
    "plt.title('Antal spel per år', fontsize=16)\n",
    "plt.xlabel('År', fontsize=14)\n",
    "plt.ylabel('Antal spel', fontsize=14)\n",
    "\n",
    "# Visa grafen\n",
    "plt.tight_layout()\n",
    "\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Samma plot med enbart Matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.bar(games_per_year.index, games_per_year.values, color='skyblue')\n",
    "plt.title('Antal spel per år', fontsize=16)\n",
    "plt.xlabel('År', fontsize=14)\n",
    "plt.ylabel('Antal spel', fontsize=14)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Animeringar (demo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "width, height = 600, 600\n",
    "ball_radius = 20\n",
    "ball_x, ball_y = width // 2, height // 2\n",
    "ball_speed_x, ball_speed_y = 5, 3\n",
    "\n",
    "# Skapa en mapp för att spara bilderna\n",
    "if not os.path.exists('frames'):\n",
    "    os.makedirs('frames')\n",
    "\n",
    "max_frame = 1000\n",
    "frame_count = 0\n",
    "\n",
    "while frame_count <= max_frame:\n",
    "    # Uppdatera position\n",
    "    ball_x += ball_speed_x\n",
    "    ball_y += ball_speed_y\n",
    "\n",
    "    # Studsa mot väggarna\n",
    "    if ball_x - ball_radius <= 0 or ball_x + ball_radius >= width:\n",
    "        ball_speed_x = -ball_speed_x\n",
    "    if ball_y - ball_radius <= 0 or ball_y + ball_radius >= height:\n",
    "        ball_speed_y = -ball_speed_y\n",
    "\n",
    "    # Skapa ny figur\n",
    "    fig, ax = plt.subplots(figsize=(6, 6), dpi=100)\n",
    "    ax.set_facecolor('black')\n",
    "    ax.set_xlim(0, width)\n",
    "    ax.set_ylim(0, height)\n",
    "    ax.set_aspect('equal')\n",
    "    ax.axis('off')\n",
    "\n",
    "    # Rita bollen\n",
    "    circle = plt.Circle((ball_x, height - ball_y), ball_radius, color='red')  # Y-spegelvänd för korrekt riktning\n",
    "    ax.add_patch(circle)\n",
    "\n",
    "    # Spara frame\n",
    "    plt.savefig(f'frames/frame_{frame_count:04d}.png', bbox_inches='tight', pad_inches=0)\n",
    "    plt.close(fig)\n",
    "\n",
    "    if frame_count % int(max_frame / 10) == 0:\n",
    "        print(f'{round(frame_count / max_frame * 100)}% done')\n",
    "    \n",
    "    frame_count += 1\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Med pygame för realtidsvisning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pygame   # används här för direkt animering från skript\n",
    "import os\n",
    "\n",
    "pygame.init()\n",
    "\n",
    "width, height = 600, 600\n",
    "screen = pygame.display.set_mode((width, height))\n",
    "pygame.display.set_caption(\"Boll i biljard\")\n",
    "\n",
    "WHITE = (255, 255, 255)\n",
    "BLACK = (0, 0, 0)\n",
    "BALL_COLOR = (255, 0, 0)\n",
    "\n",
    "ball_radius = 20\n",
    "ball_x, ball_y = width // 2, height // 2\n",
    "ball_speed_x, ball_speed_y = 5, 3\n",
    "\n",
    "if not os.path.exists('frames'):\n",
    "    os.makedirs('frames')\n",
    "\n",
    "max_frame = 1000\n",
    "frame_count = 0\n",
    "running = True\n",
    "while running:\n",
    "    for event in pygame.event.get():\n",
    "        if event.type == pygame.QUIT:\n",
    "            running = False\n",
    "\n",
    "    ball_x += ball_speed_x\n",
    "    ball_y += ball_speed_y\n",
    "\n",
    "    if ball_x - ball_radius <= 0 or ball_x + ball_radius >= width:\n",
    "        ball_speed_x = -ball_speed_x\n",
    "    if ball_y - ball_radius <= 0 or ball_y + ball_radius >= height:\n",
    "        ball_speed_y = -ball_speed_y\n",
    "\n",
    "    screen.fill(BLACK)\n",
    "\n",
    "    pygame.draw.circle(screen, BALL_COLOR, (ball_x, ball_y), ball_radius)\n",
    "\n",
    "    #pygame.image.save(screen, f\"frames/frame_{frame_count:04d}.png\")\n",
    "    frame_count += 1\n",
    "    pygame.display.flip()\n",
    "    pygame.time.delay(10)\n",
    "    if frame_count % int(max_frame/10) == 0:\n",
    "        print(f'{round(frame_count/max_frame*100)}% done')\n",
    "    if frame_count > max_frame:\n",
    "        break\n",
    "\n",
    "pygame.quit()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Gör png-filer till film (FFmpeg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.system('ffmpeg -r 60 -f image2 -pattern_type glob -i \"frames/*.png\" -pix_fmt yuv420p frames/tmp.mov')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [Länk till ett 100-tal matte/fysik-animeringar](https://www.youtube.com/@animations_ag) (Alex YT-kanal)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (venv)",
   "language": "python",
   "name": "venv"
  },
  "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.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
