{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7780218d",
   "metadata": {},
   "source": [
    "# 🎯 Jelek és Rendszerek — 20 Gyakorlat (II. sorozat)\n",
    "\n",
    "**Miskolci Egyetem** — Születési dátum: **1973.10.24.**\n",
    "\n",
    "Paraméterek:\n",
    "- A=1, B=9, C=7, D=3, E=1, F=0, G=2, H=4\n",
    "- σ₁=2, σ₂=3, ω₁=4, ω₂=7, f₁=3, f₂=7\n",
    "\n",
    "> 📌 **Minden feladat tartalmaz:**\n",
    "> 1. Feladatleírás\n",
    "> 2. Megoldás kóddal + vizualizáció\n",
    "> 3. Ellenőrzés / fizikai értelmezés\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec6146d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy import signal\n",
    "from scipy.fft import fft, fftfreq, ifft\n",
    "from scipy.signal import convolve, lfilter, freqz, butter, firwin\n",
    "\n",
    "plt.rcParams.update({\n",
    "    'figure.figsize': (12, 4), 'figure.dpi': 100,\n",
    "    'axes.facecolor': '#0a0e1a', 'figure.facecolor': '#0a0e1a',\n",
    "    'axes.edgecolor': '#2a3a5c', 'axes.labelcolor': '#c0d0e0',\n",
    "    'xtick.color': '#8090a0', 'ytick.color': '#8090a0',\n",
    "    'text.color': '#d0e0f0', 'grid.color': '#1a2a4a', 'grid.alpha': 0.5,\n",
    "    'font.size': 10, 'axes.grid': True\n",
    "})\n",
    "\n",
    "# Születési dátum paraméterek\n",
    "A, B, C, D, E, F, G, H_bd = 1, 9, 7, 3, 1, 0, 2, 4\n",
    "sigma1, sigma2 = 2, 3\n",
    "omega1, omega2 = 4, 7\n",
    "f1, f2 = 3, 7\n",
    "\n",
    "print(\"✅ Importok és paraméterek betöltve.\")\n",
    "print(f\"   σ₁={sigma1}, σ₂={sigma2}, ω₁={omega1}, ω₂={omega2}, f₁={f1}, f₂={f2}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49c34141",
   "metadata": {},
   "source": [
    "---\n",
    "## 1. feladat — Az e^{jωt} forgó vektor 3D-ben\n",
    "\n",
    "**Feladat:** Ábrázold az $e^{j\\omega_1 t}$ komplex exponenciálist 3D-ben, ahol:\n",
    "- X tengely: idő (t)\n",
    "- Y tengely: Re{$e^{j\\omega_1 t}$} = cos(ω₁t)\n",
    "- Z tengely: Im{$e^{j\\omega_1 t}$} = sin(ω₁t)\n",
    "\n",
    "Mutasd meg, hogy a forgó vektor időbeli vetülete a cos és sin hullám!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7e0a45b",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = np.linspace(0, 4*np.pi/omega1, 500)\n",
    "z_complex = np.exp(1j * omega1 * t)\n",
    "\n",
    "fig = plt.figure(figsize=(14, 6))\n",
    "\n",
    "# 3D spiral\n",
    "ax1 = fig.add_subplot(121, projection='3d')\n",
    "ax1.plot(t, z_complex.real, z_complex.imag, color='#a78bfa', linewidth=2)\n",
    "ax1.plot(t, z_complex.real, np.zeros_like(t)-1.2, color='#38bdf8', linewidth=1, alpha=0.5, label='cos(ω₁t)')\n",
    "ax1.plot(t, np.ones_like(t)*1.2, z_complex.imag, color='#ec4899', linewidth=1, alpha=0.5, label='sin(ω₁t)')\n",
    "ax1.set_xlabel('t [s]'); ax1.set_ylabel('Re'); ax1.set_zlabel('Im')\n",
    "ax1.set_title(f'e^{{jω₁t}}, ω₁={omega1} rad/s — 3D spirál')\n",
    "ax1.set_facecolor('#0a0e1a')\n",
    "ax1.legend()\n",
    "\n",
    "# 2D projections\n",
    "ax2 = fig.add_subplot(122)\n",
    "ax2.plot(t, z_complex.real, color='#38bdf8', linewidth=2, label=f'cos({omega1}t) = Re')\n",
    "ax2.plot(t, z_complex.imag, color='#ec4899', linewidth=2, label=f'sin({omega1}t) = Im')\n",
    "ax2.axhline(0, color='#2a3a5c', linewidth=0.5)\n",
    "ax2.set_xlabel('t [s]'); ax2.set_ylabel('Amplitúdó')\n",
    "ax2.set_title('Vetületek — a forgó vektor árnyékai')\n",
    "ax2.legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ A cos({omega1}t) és sin({omega1}t) az e^{{j{omega1}t}} vetülete a valós ill. képzetes tengelyre.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57524df7",
   "metadata": {},
   "source": [
    "---\n",
    "## 2. feladat — j-vel szorzás = 90° forgatás\n",
    "\n",
    "**Feladat:** Indulj z₀ = σ₁ + jσ₂ = 2+3j komplex számból. Szorozd meg j-vel 4-szer egymás után, és ábrázold mindegyik lépést a komplex síkon. Ellenőrizd, hogy 4 szorzás után visszatérsz z₀-hoz!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "267021cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "z0 = complex(sigma1, sigma2)\n",
    "steps = [z0]\n",
    "for _ in range(4):\n",
    "    steps.append(steps[-1] * 1j)\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7, 7))\n",
    "colors = ['#22c55e', '#38bdf8', '#f87171', '#fbbf24', '#22c55e']\n",
    "labels = ['z₀', 'z₀·j', 'z₀·j²', 'z₀·j³', 'z₀·j⁴=z₀']\n",
    "\n",
    "for i in range(5):\n",
    "    z = steps[i]\n",
    "    ax.plot(z.real, z.imag, 'o', color=colors[i], markersize=12, zorder=5)\n",
    "    ax.annotate(f'{labels[i]}\\n({z.real:.1f}+{z.imag:.1f}j)',\n",
    "                (z.real, z.imag), textcoords='offset points', xytext=(10, 10),\n",
    "                color=colors[i], fontsize=9, fontweight='bold')\n",
    "    if i > 0:\n",
    "        ax.annotate('', xy=(steps[i].real, steps[i].imag),\n",
    "                    xytext=(steps[i-1].real, steps[i-1].imag),\n",
    "                    arrowprops=dict(arrowstyle='->', color=colors[i], lw=2))\n",
    "        mid = (steps[i] + steps[i-1]) / 2\n",
    "        ax.text(mid.real, mid.imag, '×j', color=colors[i], fontsize=11, ha='center', fontweight='bold')\n",
    "\n",
    "# Unit circle reference\n",
    "theta = np.linspace(0, 2*np.pi, 100)\n",
    "R = abs(z0)\n",
    "ax.plot(R*np.cos(theta), R*np.sin(theta), '--', color='#a78bfa', alpha=0.2, linewidth=1)\n",
    "ax.axhline(0, color='#2a3a5c'); ax.axvline(0, color='#2a3a5c')\n",
    "ax.set_xlabel('Re'); ax.set_ylabel('Im')\n",
    "ax.set_title(f'j-vel szorzás = 90° forgatás | z₀ = {z0}')\n",
    "ax.set_aspect('equal')\n",
    "plt.tight_layout(); plt.show()\n",
    "\n",
    "print(f\"z₀ = {steps[0]}\")\n",
    "for i in range(1, 5):\n",
    "    print(f\"×j → {steps[i]}  (szög: {np.angle(steps[i])*180/np.pi:.0f}°)\")\n",
    "print(f\"\\n✅ z₀·j⁴ = {steps[4]} = z₀ → 4×90° = 360° = teljes kör!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5fdb04f1",
   "metadata": {},
   "source": [
    "---\n",
    "## 3. feladat — Euler-formula numerikus ellenőrzése\n",
    "\n",
    "**Feladat:** Ellenőrizd numerikusan, hogy $e^{j\\theta} = \\cos\\theta + j\\sin\\theta$ pontosan igaz. Számold ki az eltérést 1000 θ értékre [0, 4π] tartományban!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c2c1ceb6",
   "metadata": {},
   "outputs": [],
   "source": [
    "theta = np.linspace(0, 4*np.pi, 1000)\n",
    "lhs = np.exp(1j * theta)\n",
    "rhs = np.cos(theta) + 1j * np.sin(theta)\n",
    "error = np.abs(lhs - rhs)\n",
    "\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 4))\n",
    "\n",
    "ax1.plot(theta, lhs.real, color='#38bdf8', linewidth=2, label='Re{e^{jθ}}')\n",
    "ax1.plot(theta, np.cos(theta), '--', color='#fbbf24', linewidth=1, label='cos(θ)')\n",
    "ax1.plot(theta, lhs.imag, color='#ec4899', linewidth=2, label='Im{e^{jθ}}')\n",
    "ax1.plot(theta, np.sin(theta), '--', color='#22c55e', linewidth=1, label='sin(θ)')\n",
    "ax1.set_xlabel('θ [rad]'); ax1.set_title('Euler-formula: tökéletes egyezés')\n",
    "ax1.legend(fontsize=8)\n",
    "\n",
    "ax2.semilogy(theta, error + 1e-20, color='#f87171', linewidth=1)\n",
    "ax2.set_xlabel('θ [rad]'); ax2.set_ylabel('|hiba|')\n",
    "ax2.set_title(f'Numerikus hiba: max = {error.max():.2e}')\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ Maximális eltérés: {error.max():.2e} — gépi pontosság (float64 ≈ 10⁻¹⁶)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19cfa599",
   "metadata": {},
   "source": [
    "---\n",
    "## 4. feladat — e^{st} = e^{σt}·e^{jωt}: a σ és ω hatása\n",
    "\n",
    "**Feladat:** Ábrázold az e^{st} jelet három σ értékre: σ = −σ₁, 0, +1, miközben ω = ω₁ fix. Mutasd meg a burkológörbét!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9396966c",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = np.linspace(0, 4, 1000)\n",
    "sigmas = [-sigma1, 0, 1]\n",
    "sigma_labels = [f'σ=−{sigma1} (stabil)', 'σ=0 (Fourier!)', 'σ=+1 (instabil)']\n",
    "sigma_colors = ['#22c55e', '#38bdf8', '#f87171']\n",
    "\n",
    "fig, axes = plt.subplots(1, 3, figsize=(15, 4), sharey=False)\n",
    "\n",
    "for i, (sig, label, col) in enumerate(zip(sigmas, sigma_labels, sigma_colors)):\n",
    "    s = complex(sig, omega1)\n",
    "    x = np.exp(s * t)\n",
    "    env = np.exp(sig * t)\n",
    "\n",
    "    axes[i].plot(t, x.real, color=col, linewidth=2, label=f'Re{{e^{{st}}}}')\n",
    "    axes[i].plot(t, env, '--', color='#fbbf24', linewidth=1, label=f'±e^{{{sig}t}} burok')\n",
    "    axes[i].plot(t, -env, '--', color='#fbbf24', linewidth=1)\n",
    "    axes[i].axhline(0, color='#2a3a5c', linewidth=0.5)\n",
    "    axes[i].set_xlabel('t [s]'); axes[i].set_title(label, color=col)\n",
    "    axes[i].legend(fontsize=7)\n",
    "    if i > 0: axes[i].set_ylim(axes[i].get_ylim()[0], min(axes[i].get_ylim()[1], 10))\n",
    "\n",
    "plt.suptitle(f'e^{{st}} ahol s = σ + jω₁, ω₁ = {omega1} rad/s', fontsize=13, color='#d0e0f0')\n",
    "plt.tight_layout(); plt.show()\n",
    "\n",
    "print(\"✅ σ<0 → csillapodó rezgés (stabil)\")\n",
    "print(\"   σ=0 → állandó rezgés (ez a Fourier világa!)\")\n",
    "print(\"   σ>0 → növekvő rezgés (INSTABIL)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd49185d",
   "metadata": {},
   "source": [
    "---\n",
    "## 5. feladat — LTI sajátfüggvény: e^{jωt} → H(jω)·e^{jωt}\n",
    "\n",
    "**Feladat:** Adott H(s) = 1/(s + σ₁). Küldj e^{jωt} jelet a rendszerbe numerikus konvolúcióval, és ellenőrizd, hogy a kimenet H(jω)·e^{jωt}!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1e82816",
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = 0.001\n",
    "t = np.arange(0, 8, dt)\n",
    "\n",
    "# Impulzusválasz: h(t) = e^{-σ₁·t}·ε(t)\n",
    "h = np.exp(-sigma1 * t) * (t >= 0)\n",
    "\n",
    "# Három frekvencia tesztelése\n",
    "test_omegas = [omega1, omega2, 12]\n",
    "fig, axes = plt.subplots(len(test_omegas), 1, figsize=(13, 9))\n",
    "\n",
    "for idx, w in enumerate(test_omegas):\n",
    "    # Bemenet\n",
    "    x_in = np.cos(w * t)\n",
    "\n",
    "    # Konvolúció (numerikus)\n",
    "    y_conv = convolve(x_in, h * dt, mode='full')[:len(t)]\n",
    "\n",
    "    # Elméleti: H(jω)·cos(ωt + ∠H)\n",
    "    H_jw = 1 / (1j * w + sigma1)\n",
    "    H_mag, H_phase = abs(H_jw), np.angle(H_jw)\n",
    "    y_theory = H_mag * np.cos(w * t + H_phase)\n",
    "\n",
    "    ax = axes[idx]\n",
    "    ax.plot(t, x_in, color='#38bdf8', linewidth=1, alpha=0.4, label='Bemenet: cos(ωt)')\n",
    "    ax.plot(t, y_conv, color='#22c55e', linewidth=2, label='Konvolúció (numerikus)')\n",
    "    ax.plot(t, y_theory, '--', color='#fbbf24', linewidth=1.5, label=f'H(jω)·cos(ωt+∠H)')\n",
    "    ax.set_title(f'ω={w}: |H|={H_mag:.3f}, ∠H={np.degrees(H_phase):.1f}°', fontsize=10)\n",
    "    ax.legend(fontsize=7, loc='upper right')\n",
    "\n",
    "plt.suptitle(f'Sajátfüggvény-tulajdonság: H(s) = 1/(s+{sigma1})', fontsize=12, color='#d0e0f0')\n",
    "plt.tight_layout(); plt.show()\n",
    "print(\"✅ A konvolúció (zöld) és H(jω)·cos(ωt+∠H) (sárga szaggatott) EGYEZIK!\")\n",
    "print(\"   → Az e^{jωt} az LTI rendszer sajátfüggvénye: az alak megmarad!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b9641d4",
   "metadata": {},
   "source": [
    "---\n",
    "## 6. feladat — Fourier = korreláció e^{−jωt}-vel\n",
    "\n",
    "**Feladat:** Számold ki az X(jω) = ∫x(t)·e^{−jωt}dt integrált numerikusan, ω söpörésével. A jel: x(t) = cos(f₁·t) + 0.6·cos(f₂·t). Ábrázold a spektrumot!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46af0f1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = 0.01\n",
    "t = np.arange(0, 20, dt)\n",
    "x = np.cos(f1 * t) + 0.6 * np.cos(f2 * t)\n",
    "\n",
    "# Kézi Fourier-transzformáció (korreláció)\n",
    "omegas = np.linspace(0, 15, 500)\n",
    "X_manual = np.zeros(len(omegas), dtype=complex)\n",
    "\n",
    "for i, w in enumerate(omegas):\n",
    "    X_manual[i] = np.sum(x * np.exp(-1j * w * t)) * dt\n",
    "\n",
    "fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(13, 9))\n",
    "\n",
    "ax1.plot(t, x, color='#38bdf8', linewidth=1)\n",
    "ax1.set_title(f'x(t) = cos({f1}t) + 0.6·cos({f2}t)'); ax1.set_xlabel('t [s]')\n",
    "\n",
    "ax2.plot(omegas, np.abs(X_manual), color='#fbbf24', linewidth=2)\n",
    "ax2.axvline(f1, color='#22c55e', linewidth=1, linestyle='--', label=f'ω={f1}')\n",
    "ax2.axvline(f2, color='#ec4899', linewidth=1, linestyle='--', label=f'ω={f2}')\n",
    "ax2.set_title('|X(jω)| — kézi Fourier (korreláció-integrál)')\n",
    "ax2.set_xlabel('ω [rad/s]'); ax2.legend()\n",
    "\n",
    "# FFT összehasonlítás\n",
    "X_fft = fft(x)\n",
    "freqs = fftfreq(len(t), dt) * 2 * np.pi  # rad/s\n",
    "mask = freqs >= 0\n",
    "\n",
    "ax3.plot(freqs[mask], np.abs(X_fft[mask]) * dt, color='#a78bfa', linewidth=2)\n",
    "ax3.axvline(f1, color='#22c55e', linewidth=1, linestyle='--')\n",
    "ax3.axvline(f2, color='#ec4899', linewidth=1, linestyle='--')\n",
    "ax3.set_title('|X(jω)| — FFT (gyors!)'); ax3.set_xlabel('ω [rad/s]')\n",
    "ax3.set_xlim(0, 15)\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ Csúcsok ω={f1} és ω={f2} rad/s-nál — pontosan ahol a jelkomponensek vannak!\")\n",
    "print(\"   A Fourier-transzformáció = korreláció az e^{−jωt} forgó vektorral.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae60061e",
   "metadata": {},
   "source": [
    "---\n",
    "## 7. feladat — Konvolúciós tétel: időbeli * = frekvenciabeli ×\n",
    "\n",
    "**Feladat:** Számold ki y = x * h-t kétféleképpen:\n",
    "1. Időbeli konvolúció\n",
    "2. FFT → szorzás → IFFT\n",
    "\n",
    "Ellenőrizd, hogy az eredmény azonos!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "af248ab1",
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = 0.01\n",
    "t = np.arange(0, 10, dt)\n",
    "x = np.cos(omega1 * t) + 0.5 * np.cos(omega2 * t)\n",
    "h = np.exp(-sigma1 * t) * (t >= 0)\n",
    "\n",
    "# Módszer 1: időbeli konvolúció\n",
    "y_time = convolve(x, h * dt, mode='full')[:len(t)]\n",
    "\n",
    "# Módszer 2: FFT → szorzás → IFFT\n",
    "N = len(t)\n",
    "X = fft(x, 2*N)\n",
    "H = fft(h * dt, 2*N)\n",
    "Y = X * H\n",
    "y_freq = np.real(ifft(Y))[:N]\n",
    "\n",
    "fig, axes = plt.subplots(3, 1, figsize=(13, 8))\n",
    "\n",
    "axes[0].plot(t, x, color='#38bdf8', linewidth=1)\n",
    "axes[0].set_title('x(t) bemenet'); axes[0].set_xlabel('t')\n",
    "\n",
    "axes[1].plot(t[:200], h[:200], color='#ec4899', linewidth=2)\n",
    "axes[1].set_title(f'h(t) = e^{{−{sigma1}t}} impulzusválasz'); axes[1].set_xlabel('t')\n",
    "\n",
    "axes[2].plot(t, y_time, color='#22c55e', linewidth=2, label='Időbeli konvolúció')\n",
    "axes[2].plot(t, y_freq, '--', color='#fbbf24', linewidth=1.5, label='FFT módszer')\n",
    "axes[2].set_title('y(t) = x(t) * h(t)'); axes[2].set_xlabel('t')\n",
    "axes[2].legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "\n",
    "err = np.max(np.abs(y_time - y_freq))\n",
    "print(f\"✅ Maximális eltérés a két módszer között: {err:.2e}\")\n",
    "print(\"   → A konvolúciós tétel működik: idő * = frekvencia ×\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c65d9489",
   "metadata": {},
   "source": [
    "---\n",
    "## 8. feladat — Laplace-pólusok → impulzusválasz\n",
    "\n",
    "**Feladat:** H(s) = 1/((s+σ₁)(s+σ₂)). Rajzold meg a pólusokat az s-síkon, és az impulzusválaszt!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "69a60159",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = np.linspace(0, 5, 1000)\n",
    "\n",
    "# Parciális törtek: 1/((s+2)(s+3)) = A/(s+2) + B/(s+3)\n",
    "A_coeff = 1 / (sigma2 - sigma1)  # 1/(3-2) = 1\n",
    "B_coeff = 1 / (sigma1 - sigma2)  # 1/(2-3) = -1\n",
    "h_t = A_coeff * np.exp(-sigma1 * t) + B_coeff * np.exp(-sigma2 * t)\n",
    "\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 5))\n",
    "\n",
    "# Pólus-zérus diagram\n",
    "ax1.axhline(0, color='#2a3a5c'); ax1.axvline(0, color='#2a3a5c')\n",
    "ax1.fill_betweenx([-5, 5], -6, 0, color='#22c55e', alpha=0.03)  # stabil régió\n",
    "ax1.fill_betweenx([-5, 5], 0, 2, color='#f87171', alpha=0.03)   # instabil\n",
    "ax1.plot(-sigma1, 0, 'x', color='#f87171', markersize=15, markeredgewidth=3, label=f's₁=−{sigma1}')\n",
    "ax1.plot(-sigma2, 0, 'x', color='#ec4899', markersize=15, markeredgewidth=3, label=f's₂=−{sigma2}')\n",
    "ax1.set_xlabel('σ (Re)'); ax1.set_ylabel('jω (Im)')\n",
    "ax1.set_title('Pólusok az s-síkon')\n",
    "ax1.set_xlim(-5, 2); ax1.set_ylim(-3, 3)\n",
    "ax1.legend(); ax1.set_aspect('equal')\n",
    "ax1.text(-3, 2.3, 'STABIL', color='#22c55e', fontsize=10)\n",
    "ax1.text(0.3, 2.3, 'INSTABIL', color='#f87171', fontsize=10)\n",
    "\n",
    "# Impulzusválasz\n",
    "ax2.plot(t, A_coeff * np.exp(-sigma1 * t), '--', color='#38bdf8', linewidth=1.5,\n",
    "         label=f'{A_coeff:.0f}·e^{{−{sigma1}t}}')\n",
    "ax2.plot(t, B_coeff * np.exp(-sigma2 * t), '--', color='#ec4899', linewidth=1.5,\n",
    "         label=f'{B_coeff:.0f}·e^{{−{sigma2}t}}')\n",
    "ax2.plot(t, h_t, color='#fbbf24', linewidth=2.5, label='h(t) = összeg')\n",
    "ax2.axhline(0, color='#2a3a5c', linewidth=0.5)\n",
    "ax2.set_xlabel('t [s]'); ax2.set_title('h(t) impulzusválasz')\n",
    "ax2.legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ H(s) = 1/((s+{sigma1})(s+{sigma2})) → h(t) = {A_coeff:.0f}·e^{{−{sigma1}t}} + ({B_coeff:.0f})·e^{{−{sigma2}t}}\")\n",
    "print(f\"   Mindkét pólus a bal félsíkon → STABIL rendszer\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92bfa4c9",
   "metadata": {},
   "source": [
    "---\n",
    "## 9. feladat — Komplex pólusok: csillapodó rezgés\n",
    "\n",
    "**Feladat:** H(s) = ω₁²/(s² + 2σ₁s + ω₁²+σ₁²). A pólusok: s = −σ₁ ± jω₁. Rajzold az s-síkot és az impulzusválaszt!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21e34253",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = np.linspace(0, 5, 1000)\n",
    "h_t = np.exp(-sigma1 * t) * np.cos(omega1 * t)\n",
    "env_p = np.exp(-sigma1 * t)\n",
    "env_m = -np.exp(-sigma1 * t)\n",
    "\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 5))\n",
    "\n",
    "# Komplex póluspár\n",
    "ax1.axhline(0, color='#2a3a5c'); ax1.axvline(0, color='#2a3a5c')\n",
    "ax1.fill_betweenx([-8, 8], -6, 0, color='#22c55e', alpha=0.03)\n",
    "ax1.plot(-sigma1, omega1, 'x', color='#d946ef', markersize=15, markeredgewidth=3,\n",
    "         label=f's = −{sigma1}+j{omega1}')\n",
    "ax1.plot(-sigma1, -omega1, 'x', color='#d946ef', markersize=15, markeredgewidth=3,\n",
    "         label=f's = −{sigma1}−j{omega1}')\n",
    "ax1.set_xlabel('σ'); ax1.set_ylabel('jω')\n",
    "ax1.set_title('Komplex konjugált póluspár')\n",
    "ax1.set_xlim(-5, 2); ax1.set_ylim(-6, 6)\n",
    "ax1.legend(); ax1.set_aspect('equal')\n",
    "\n",
    "# Csúcspontokat kötjük össze szaggatott vonallal\n",
    "ax1.plot([-sigma1, 0], [omega1, 0], '--', color='#a78bfa', alpha=0.3)\n",
    "ax1.text(-sigma1-1.5, omega1+0.5, f'|s|={np.sqrt(sigma1**2+omega1**2):.2f}', color='#a78bfa', fontsize=8)\n",
    "\n",
    "# Impulzusválasz\n",
    "ax2.plot(t, h_t, color='#38bdf8', linewidth=2, label=f'e^{{−{sigma1}t}}·cos({omega1}t)')\n",
    "ax2.plot(t, env_p, '--', color='#fbbf24', linewidth=1, label=f'±e^{{−{sigma1}t}} burok')\n",
    "ax2.plot(t, env_m, '--', color='#fbbf24', linewidth=1)\n",
    "ax2.axhline(0, color='#2a3a5c', linewidth=0.5)\n",
    "ax2.set_xlabel('t [s]'); ax2.set_title('h(t) = csillapodó rezgés')\n",
    "ax2.legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ Komplex pólusok: s = −{sigma1} ± j{omega1}\")\n",
    "print(f\"   σ={sigma1} → csillapítás sebessége | ω={omega1} → rezgés frekvenciája\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d9d347a",
   "metadata": {},
   "source": [
    "---\n",
    "## 10. feladat — Bode-diagram: H(s) = ω₁/(s+ω₁)\n",
    "\n",
    "**Feladat:** Rajzold meg az aluláteresztő szűrő H(s)=ω₁/(s+ω₁) Bode-diagramját (amplitúdó + fázis). Jelöld a −3 dB-es pontot!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b7faae9",
   "metadata": {},
   "outputs": [],
   "source": [
    "w = np.logspace(-1, 2, 1000)\n",
    "H = omega1 / (1j * w + omega1)\n",
    "\n",
    "fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 7), sharex=True)\n",
    "\n",
    "# Amplitúdó\n",
    "ax1.semilogx(w, 20 * np.log10(np.abs(H)), color='#38bdf8', linewidth=2)\n",
    "ax1.axhline(-3, color='#f87171', linewidth=1, linestyle='--', label='−3 dB')\n",
    "ax1.axvline(omega1, color='#fbbf24', linewidth=1, linestyle='--', label=f'ω₀={omega1} rad/s')\n",
    "ax1.set_ylabel('|H(jω)| [dB]'); ax1.set_title(f'Bode-diagram: H(s) = {omega1}/(s+{omega1})')\n",
    "ax1.legend()\n",
    "\n",
    "# Aszimptotikus közelítés\n",
    "w_low = w[w <= omega1]; w_high = w[w > omega1]\n",
    "asym_low = np.zeros_like(w_low)\n",
    "asym_high = -20 * np.log10(w_high / omega1)\n",
    "ax1.semilogx(w_low, asym_low, '--', color='#22c55e', linewidth=1, alpha=0.5)\n",
    "ax1.semilogx(w_high, asym_high, '--', color='#22c55e', linewidth=1, alpha=0.5, label='Aszimptota')\n",
    "ax1.legend(fontsize=8)\n",
    "\n",
    "# Fázis\n",
    "ax2.semilogx(w, np.degrees(np.angle(H)), color='#ec4899', linewidth=2)\n",
    "ax2.axhline(-45, color='#f87171', linewidth=1, linestyle='--', label='−45° (töréspontnál)')\n",
    "ax2.axvline(omega1, color='#fbbf24', linewidth=1, linestyle='--')\n",
    "ax2.set_ylabel('∠H(jω) [°]'); ax2.set_xlabel('ω [rad/s]')\n",
    "ax2.legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ Töréspont: ω₀ = {omega1} rad/s → −3 dB, −45°\")\n",
    "print(f\"   Felette: −20 dB/dekád meredekség (elsőrendű rendszer)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b80a5b19",
   "metadata": {},
   "source": [
    "---\n",
    "## 11. feladat — z-transzformáció: pólus az egységkörön belül = stabil\n",
    "\n",
    "**Feladat:** x[k] = (0.B)^k = (0.9)^k. Rajzold meg a z-síkot (pólus helye), az egységkört, és az x[k] jelet!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "83d5bb6c",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = B / 10  # 0.9\n",
    "k = np.arange(0, 40)\n",
    "x_k = a ** k\n",
    "\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 5))\n",
    "\n",
    "# z-sík\n",
    "theta = np.linspace(0, 2*np.pi, 100)\n",
    "ax1.plot(np.cos(theta), np.sin(theta), '--', color='#a78bfa', linewidth=1, label='Egységkör |z|=1')\n",
    "ax1.axhline(0, color='#2a3a5c'); ax1.axvline(0, color='#2a3a5c')\n",
    "ax1.plot(a, 0, 'x', color='#f87171', markersize=15, markeredgewidth=3, label=f'Pólus: z={a}')\n",
    "ax1.fill(np.cos(theta), np.sin(theta), color='#22c55e', alpha=0.03)\n",
    "ax1.set_xlabel('Re(z)'); ax1.set_ylabel('Im(z)')\n",
    "ax1.set_title('z-sík: pólus az egységkörön BELÜL')\n",
    "ax1.set_aspect('equal'); ax1.set_xlim(-1.5, 1.5); ax1.set_ylim(-1.5, 1.5)\n",
    "ax1.legend()\n",
    "stab = \"STABIL ✓\" if abs(a) < 1 else \"INSTABIL ✗\"\n",
    "ax1.text(a, 0.15, f'|z|={abs(a):.1f} {\"<\" if abs(a)<1 else \">\"} 1 → {stab}',\n",
    "         color='#22c55e' if abs(a)<1 else '#f87171', fontsize=10, ha='center')\n",
    "\n",
    "# Jel\n",
    "ax2.stem(k, x_k, linefmt='#38bdf8', markerfmt='o', basefmt='#2a3a5c')\n",
    "ax2.set_xlabel('k'); ax2.set_ylabel('x[k]')\n",
    "ax2.set_title(f'x[k] = {a}^k — {\"csökkenő\" if a<1 else \"növekvő\"}')\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ z = {a}, |z| = {abs(a)} < 1 → egységkörön BELÜL → STABIL\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "719e6c5a",
   "metadata": {},
   "source": [
    "---\n",
    "## 12. feladat — FIR vs IIR szűrő összehasonlítás\n",
    "\n",
    "**Feladat:** Tervezz egy aluláteresztő szűrőt fc = ω₁/(2π) Hz-re, fs = 100 Hz mintavétellel:\n",
    "1. FIR (31-tap)\n",
    "2. IIR (Butterworth, 4. rend)\n",
    "\n",
    "Hasonlítsd össze a frekvenciaválaszt és az impulzusválaszt!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8199f55c",
   "metadata": {},
   "outputs": [],
   "source": [
    "fs = 100\n",
    "fc = omega1 / (2 * np.pi)  # Hz-ben\n",
    "wn = fc / (fs / 2)  # normált frekvencia\n",
    "\n",
    "# FIR szűrő\n",
    "N_fir = 31\n",
    "h_fir = firwin(N_fir, wn)\n",
    "\n",
    "# IIR szűrő (Butterworth)\n",
    "b_iir, a_iir = butter(4, wn)\n",
    "\n",
    "# Frekvenciaválasz\n",
    "w_fir, H_fir = freqz(h_fir, [1], worN=1024, fs=fs)\n",
    "w_iir, H_iir = freqz(b_iir, a_iir, worN=1024, fs=fs)\n",
    "\n",
    "fig, axes = plt.subplots(2, 2, figsize=(14, 8))\n",
    "\n",
    "# Amplitúdó\n",
    "axes[0,0].plot(w_fir, 20*np.log10(np.abs(H_fir)+1e-10), color='#38bdf8', linewidth=2, label='FIR 31-tap')\n",
    "axes[0,0].plot(w_iir, 20*np.log10(np.abs(H_iir)+1e-10), color='#ec4899', linewidth=2, label='IIR Butter-4')\n",
    "axes[0,0].axvline(fc, color='#fbbf24', linestyle='--', linewidth=1, label=f'fc={fc:.2f} Hz')\n",
    "axes[0,0].axhline(-3, color='#f87171', linestyle=':', linewidth=1)\n",
    "axes[0,0].set_ylabel('dB'); axes[0,0].set_title('Amplitúdóválasz')\n",
    "axes[0,0].set_xlim(0, fs/2); axes[0,0].legend(fontsize=8)\n",
    "\n",
    "# Fázis\n",
    "axes[0,1].plot(w_fir, np.unwrap(np.angle(H_fir))*180/np.pi, color='#38bdf8', linewidth=2, label='FIR')\n",
    "axes[0,1].plot(w_iir, np.unwrap(np.angle(H_iir))*180/np.pi, color='#ec4899', linewidth=2, label='IIR')\n",
    "axes[0,1].set_ylabel('Fázis [°]'); axes[0,1].set_title('Fázisválasz')\n",
    "axes[0,1].set_xlim(0, fs/2); axes[0,1].legend(fontsize=8)\n",
    "\n",
    "# FIR impulzusválasz\n",
    "axes[1,0].stem(range(N_fir), h_fir, linefmt='#38bdf8', markerfmt='o', basefmt='#2a3a5c')\n",
    "axes[1,0].set_title('FIR impulzusválasz (véges!)'); axes[1,0].set_xlabel('k')\n",
    "\n",
    "# IIR impulzusválasz\n",
    "k_iir = np.arange(60)\n",
    "imp = np.zeros(60); imp[0] = 1\n",
    "h_iir_resp = lfilter(b_iir, a_iir, imp)\n",
    "axes[1,1].stem(k_iir, h_iir_resp, linefmt='#ec4899', markerfmt='o', basefmt='#2a3a5c')\n",
    "axes[1,1].set_title('IIR impulzusválasz (végtelen!)'); axes[1,1].set_xlabel('k')\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ FIR: {N_fir} együttható, MINDIG stabil, lineáris fázis\")\n",
    "print(f\"   IIR: 2×5 együttható, meredekebb levágás, de NEM lineáris fázis\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "257ddb9d",
   "metadata": {},
   "source": [
    "---\n",
    "## 13. feladat — Chirp jel és illesztett szűrő\n",
    "\n",
    "**Feladat:** Generálj LFM chirp jelet (f₁=3 → f₂=7 Hz, T=2s). Alkalmazd az illesztett szűrőt, és mutasd meg az impulzuskompressziót!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "494eaf20",
   "metadata": {},
   "outputs": [],
   "source": [
    "T_chirp = sigma1  # 2 s\n",
    "fs_chirp = 200\n",
    "t_chirp = np.arange(0, T_chirp, 1/fs_chirp)\n",
    "f_start, f_end = f1, f2\n",
    "\n",
    "# Chirp\n",
    "mu = (f_end - f_start) / T_chirp\n",
    "chirp_sig = np.cos(2*np.pi*(f_start * t_chirp + 0.5 * mu * t_chirp**2))\n",
    "\n",
    "# Illesztett szűrő = időben tükrözött chirp\n",
    "matched = chirp_sig[::-1]\n",
    "\n",
    "# Kompresszió = korreláció\n",
    "compressed = np.correlate(chirp_sig, matched, mode='full')\n",
    "t_comp = np.arange(len(compressed)) / fs_chirp - T_chirp\n",
    "compressed /= np.max(np.abs(compressed))\n",
    "\n",
    "fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(13, 9))\n",
    "\n",
    "ax1.plot(t_chirp, chirp_sig, color='#38bdf8', linewidth=1)\n",
    "ax1.set_title(f'LFM chirp: {f_start}→{f_end} Hz, T={T_chirp}s')\n",
    "ax1.set_xlabel('t [s]')\n",
    "\n",
    "# Spektrogram\n",
    "ax2.specgram(chirp_sig, Fs=fs_chirp, NFFT=64, noverlap=56, cmap='magma')\n",
    "ax2.set_ylabel('f [Hz]'); ax2.set_title('Spektrogram — lineárisan növekvő frekvencia')\n",
    "ax2.set_ylim(0, 15)\n",
    "\n",
    "ax3.plot(t_comp, compressed, color='#22c55e', linewidth=1.5)\n",
    "ax3.axhline(0, color='#2a3a5c', linewidth=0.5)\n",
    "ax3.set_title(f'Impulzuskompresszió: TBP = T·Δf = {T_chirp}×{f_end-f_start} = {T_chirp*(f_end-f_start):.0f}')\n",
    "ax3.set_xlabel('t [s]')\n",
    "ax3.axvline(0, color='#fbbf24', linewidth=1, linestyle='--', label='Csúcs (éles!)')\n",
    "ax3.legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ TBP = {T_chirp*(f_end-f_start):.0f} → a {T_chirp}s hosszú jel ~{1/(f_end-f_start):.3f}s éles csúccsá tömörül!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1691a433",
   "metadata": {},
   "source": [
    "---\n",
    "## 14. feladat — Határozatlansági elv: Δt·Δω ≥ ½\n",
    "\n",
    "**Feladat:** Generálj Gauss-impulzusokat különböző σ-val, és mutasd meg, hogy Δt·Δω = ½ (pontosan eléri a minimumot)!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c238a33c",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(3, 2, figsize=(14, 10))\n",
    "sigmas_gauss = [0.5, 1.0, 2.0]\n",
    "\n",
    "for i, sg in enumerate(sigmas_gauss):\n",
    "    t = np.linspace(-5, 5, 2000)\n",
    "    dt_s = t[1] - t[0]\n",
    "    x = np.exp(-t**2 / (2 * sg**2))\n",
    "    x /= np.sqrt(np.sum(x**2) * dt_s)  # normalizálás\n",
    "\n",
    "    # Időbeli szélesség\n",
    "    delta_t = sg\n",
    "\n",
    "    # FFT → spektrum\n",
    "    X = fft(x)\n",
    "    freqs = fftfreq(len(t), dt_s)\n",
    "    X_mag = np.abs(X) * dt_s\n",
    "\n",
    "    # Frekvenciabeli szélesség\n",
    "    delta_omega = 1 / (2 * sg)\n",
    "\n",
    "    tbp = delta_t * delta_omega\n",
    "\n",
    "    axes[i, 0].plot(t, x, color='#a78bfa', linewidth=2)\n",
    "    axes[i, 0].axvspan(-delta_t, delta_t, color='#a78bfa', alpha=0.05)\n",
    "    axes[i, 0].set_title(f'σ={sg}: Δt = σ = {delta_t:.2f}')\n",
    "    axes[i, 0].set_xlabel('t')\n",
    "    axes[i, 0].set_xlim(-5, 5)\n",
    "\n",
    "    axes[i, 1].plot(np.fft.fftshift(freqs)*2*np.pi, np.fft.fftshift(X_mag), color='#fbbf24', linewidth=2)\n",
    "    axes[i, 1].set_title(f'Δω = 1/(2σ) = {delta_omega:.2f} → Δt·Δω = {tbp:.3f} ≈ 0.5')\n",
    "    axes[i, 1].set_xlabel('ω [rad/s]')\n",
    "    axes[i, 1].set_xlim(-5, 5)\n",
    "\n",
    "plt.suptitle('Határozatlansági elv: Gauss = optimális (Δt·Δω = ½)', fontsize=13, color='#d0e0f0')\n",
    "plt.tight_layout(); plt.show()\n",
    "print(\"✅ A Gauss-impulzus az EGYETLEN jel, ahol Δt·Δω = ½ (minimum)!\")\n",
    "print(\"   Szélesebb időben → keskenyebb frekvenciában, és fordítva.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5663b708",
   "metadata": {},
   "source": [
    "---\n",
    "## 15. feladat — Parseval-tétel: energia az időben = energia a frekvenciában\n",
    "\n",
    "**Feladat:** Ellenőrizd: ∫|x(t)|²dt = (1/2π)∫|X(jω)|²dω egy exponenciálisan csökkenő jelre!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0297484e",
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = 0.001\n",
    "t = np.arange(0, 20, dt)\n",
    "x = np.exp(-sigma1 * t) * (t >= 0)\n",
    "\n",
    "# Időbeli energia\n",
    "E_time = np.sum(np.abs(x)**2) * dt\n",
    "\n",
    "# Frekvenciabeli energia\n",
    "X = fft(x)\n",
    "freqs = fftfreq(len(t), dt)\n",
    "dw = 2 * np.pi * (freqs[1] - freqs[0])\n",
    "E_freq = np.sum(np.abs(X * dt)**2) * dw / (2 * np.pi)\n",
    "\n",
    "# Elméleti: ∫₀^∞ e^{-2σt} dt = 1/(2σ)\n",
    "E_theory = 1 / (2 * sigma1)\n",
    "\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 4))\n",
    "\n",
    "ax1.plot(t[:500], np.abs(x[:500])**2, color='#38bdf8', linewidth=2)\n",
    "ax1.fill_between(t[:500], np.abs(x[:500])**2, alpha=0.1, color='#38bdf8')\n",
    "ax1.set_title(f'|x(t)|² — időbeli energia: {E_time:.4f}')\n",
    "ax1.set_xlabel('t')\n",
    "\n",
    "mask = (freqs > -20) & (freqs < 20)\n",
    "ax2.plot(freqs[mask]*2*np.pi, np.abs(X[mask]*dt)**2, color='#fbbf24', linewidth=2)\n",
    "ax2.fill_between(freqs[mask]*2*np.pi, np.abs(X[mask]*dt)**2, alpha=0.1, color='#fbbf24')\n",
    "ax2.set_title(f'|X(jω)|² — frekvencia energia: {E_freq:.4f}')\n",
    "ax2.set_xlabel('ω [rad/s]')\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"Időbeli:    E = {E_time:.6f}\")\n",
    "print(f\"Frekvencia: E = {E_freq:.6f}\")\n",
    "print(f\"Elméleti:   E = 1/(2·{sigma1}) = {E_theory:.6f}\")\n",
    "print(f\"\\n✅ Parseval-tétel: az energia megmarad! Eltérés: {abs(E_time-E_freq)/E_theory*100:.2f}%\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6d7c1b4",
   "metadata": {},
   "source": [
    "---\n",
    "## 16. feladat — DFT felbontás: Δf = fs/N\n",
    "\n",
    "**Feladat:** Két közeli frekvencia (f₁ és f₁+Δf) szétválasztása. Mennyi N kell, hogy a DFT megkülönböztesse őket?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46201e82",
   "metadata": {},
   "outputs": [],
   "source": [
    "fs = 100\n",
    "f_a = f1\n",
    "delta_f_vals = [2.0, 0.5, 0.1]\n",
    "\n",
    "fig, axes = plt.subplots(3, 2, figsize=(14, 10))\n",
    "\n",
    "for i, df in enumerate(delta_f_vals):\n",
    "    f_b = f_a + df\n",
    "    N_needed = int(np.ceil(fs / df))\n",
    "\n",
    "    # Generálás N_needed ponttal\n",
    "    N = max(N_needed, 128)\n",
    "    t = np.arange(N) / fs\n",
    "    x = np.cos(2*np.pi*f_a*t) + np.cos(2*np.pi*f_b*t)\n",
    "\n",
    "    X = fft(x)\n",
    "    freqs = fftfreq(N, 1/fs)\n",
    "    mask = freqs >= 0\n",
    "\n",
    "    axes[i,0].plot(t[:min(500,N)], x[:min(500,N)], color='#38bdf8', linewidth=1)\n",
    "    axes[i,0].set_title(f'Δf = {df} Hz → N ≥ {N_needed} (használt: {N})')\n",
    "    axes[i,0].set_xlabel('t [s]')\n",
    "\n",
    "    axes[i,1].plot(freqs[mask], 2/N * np.abs(X[mask]), color='#fbbf24', linewidth=1.5)\n",
    "    axes[i,1].axvline(f_a, color='#22c55e', linewidth=1, linestyle='--', alpha=0.5)\n",
    "    axes[i,1].axvline(f_b, color='#ec4899', linewidth=1, linestyle='--', alpha=0.5)\n",
    "    axes[i,1].set_xlim(f_a - 2, f_b + 2)\n",
    "    axes[i,1].set_title(f'Δf_DFT = fs/N = {fs}/{N} = {fs/N:.3f} Hz')\n",
    "    axes[i,1].set_xlabel('f [Hz]')\n",
    "\n",
    "plt.suptitle(f'DFT felbontás: Δf = fs/N — két közeli frekvencia szétválasztása', fontsize=12, color='#d0e0f0')\n",
    "plt.tight_layout(); plt.show()\n",
    "print(\"✅ Minél közelebb a két frekvencia, annál több minta (N) kell a szétválasztáshoz!\")\n",
    "print(f\"   Δf = fs/N → N = fs/Δf\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13fe9cf0",
   "metadata": {},
   "source": [
    "---\n",
    "## 17. feladat — Konvolúció = mintakeresés (illesztett szűrő)\n",
    "\n",
    "**Feladat:** Rejtsd el egy rövid mintát egy zajos jelben, és keresd meg konvolúcióval (korrelációval)!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f8b7e9b",
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(19731024)\n",
    "\n",
    "# Minta (rövid chirp-szerű)\n",
    "k_pattern = np.arange(30)\n",
    "pattern = np.sin(2 * np.pi * k_pattern / 10) * np.hanning(30)\n",
    "\n",
    "# Zajos jel, benne a minta 3 helyen\n",
    "N = 500\n",
    "noise = np.random.randn(N) * 0.5\n",
    "signal_clean = np.zeros(N)\n",
    "positions = [80, 230, 370]\n",
    "for p in positions:\n",
    "    signal_clean[p:p+30] += pattern\n",
    "\n",
    "x = signal_clean + noise\n",
    "\n",
    "# Korreláció (= konvolúció tükrözött mintával)\n",
    "corr = np.correlate(x, pattern, mode='same')\n",
    "corr /= np.max(np.abs(corr))\n",
    "\n",
    "fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(13, 8))\n",
    "\n",
    "ax1.plot(k_pattern, pattern, color='#ec4899', linewidth=2)\n",
    "ax1.set_title('Keresett minta'); ax1.set_xlabel('k')\n",
    "\n",
    "ax2.plot(x, color='#38bdf8', linewidth=0.8)\n",
    "for p in positions:\n",
    "    ax2.axvspan(p, p+30, color='#22c55e', alpha=0.1)\n",
    "ax2.set_title('Zajos jel (a minta 3 helyen van elrejtve)'); ax2.set_xlabel('k')\n",
    "\n",
    "ax3.plot(corr, color='#fbbf24', linewidth=1.5)\n",
    "ax3.axhline(0.5, color='#f87171', linewidth=1, linestyle='--', label='Küszöb')\n",
    "# Csúcsok detektálása\n",
    "peaks = np.where(corr > 0.5)[0]\n",
    "for p in peaks[::1]:\n",
    "    ax3.axvline(p, color='#22c55e', linewidth=0.5, alpha=0.3)\n",
    "ax3.set_title('Korreláció kimenet — csúcsok = találatok!'); ax3.set_xlabel('k')\n",
    "ax3.legend()\n",
    "\n",
    "plt.tight_layout(); plt.show()\n",
    "print(f\"✅ A minta {len(positions)} helyen volt elrejtve → a korreláció {len(positions)} csúcsot ad!\")\n",
    "print(\"   Ez az illesztett szűrő (matched filter) elve — radar, delfin echolokáció!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54b81fb6",
   "metadata": {},
   "source": [
    "---\n",
    "## 18. feladat — Ablakfüggvények hatása a spektrumra\n",
    "\n",
    "**Feladat:** Ugyanaz a jel, de különböző ablakokkal (téglalap, Hanning, Blackman). Hogyan változik a spektrum?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f766c92",
   "metadata": {},
   "outputs": [],
   "source": [
    "fs = 200\n",
    "N = 256\n",
    "t = np.arange(N) / fs\n",
    "x = np.cos(2*np.pi*f1*t) + 0.01*np.cos(2*np.pi*(f1+3)*t)  # erős + gyenge komponens\n",
    "\n",
    "windows = {\n",
    "    'Téglalap (nincs ablak)': np.ones(N),\n",
    "    'Hanning': np.hanning(N),\n",
    "    'Blackman': np.blackman(N),\n",
    "}\n",
    "\n",
    "fig, axes = plt.subplots(len(windows), 2, figsize=(14, 9))\n",
    "colors = ['#38bdf8', '#22c55e', '#ec4899']\n",
    "\n",
    "for i, (name, win) in enumerate(windows.items()):\n",
    "    x_win = x * win\n",
    "    X = fft(x_win)\n",
    "    freqs = fftfreq(N, 1/fs)\n",
    "    mask = freqs >= 0\n",
    "    mag_db = 20 * np.log10(np.abs(X[mask]) / np.max(np.abs(X[mask])) + 1e-10)\n",
    "\n",
    "    axes[i, 0].plot(t, x_win, color=colors[i], linewidth=1)\n",
    "    axes[i, 0].set_title(name); axes[i, 0].set_xlabel('t [s]')\n",
    "\n",
    "    axes[i, 1].plot(freqs[mask], mag_db, color=colors[i], linewidth=1.5)\n",
    "    axes[i, 1].set_ylim(-100, 5); axes[i, 1].set_xlim(0, 20)\n",
    "    axes[i, 1].axvline(f1, color='#fbbf24', linewidth=0.5, linestyle='--')\n",
    "    axes[i, 1].axvline(f1+3, color='#fbbf24', linewidth=0.5, linestyle='--')\n",
    "    axes[i, 1].set_title(f'{name} — spektrum [dB]')\n",
    "    axes[i, 1].set_xlabel('f [Hz]')\n",
    "\n",
    "plt.suptitle(f'Ablakfüggvények: erős ({f1} Hz) + gyenge ({f1+3} Hz, −40 dB) komponens', fontsize=12, color='#d0e0f0')\n",
    "plt.tight_layout(); plt.show()\n",
    "print(\"✅ Téglalap: széles melléknyalábok → a gyenge komponens eltűnik\")\n",
    "print(\"   Hanning: jobb melléknyaláb-elnyomás → gyenge jel felfedezhető\")\n",
    "print(\"   Blackman: legjobb elnyomás, de szélesebb főnyaláb\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd435e99",
   "metadata": {},
   "source": [
    "---\n",
    "## 19. feladat — Pólus mozgatása a z-síkon: stabilitás-vizsgálat\n",
    "\n",
    "**Feladat:** H(z) = 1/(z−p) szűrő, ahol p pólust mozgatjuk: |p| < 1, = 1, > 1. Mutasd meg az impulzusválaszt!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a960763a",
   "metadata": {},
   "outputs": [],
   "source": [
    "poles = [0.5, 0.9, 0.99, 1.0, 1.05]\n",
    "fig, axes = plt.subplots(2, len(poles), figsize=(16, 7))\n",
    "\n",
    "theta_c = np.linspace(0, 2*np.pi, 100)\n",
    "k = np.arange(50)\n",
    "\n",
    "for i, p in enumerate(poles):\n",
    "    # z-sík\n",
    "    ax_z = axes[0, i]\n",
    "    ax_z.plot(np.cos(theta_c), np.sin(theta_c), '--', color='#a78bfa', linewidth=1)\n",
    "    ax_z.axhline(0, color='#2a3a5c'); ax_z.axvline(0, color='#2a3a5c')\n",
    "    col = '#22c55e' if abs(p) < 1 else ('#fbbf24' if abs(p) == 1 else '#f87171')\n",
    "    ax_z.plot(p, 0, 'x', color=col, markersize=12, markeredgewidth=3)\n",
    "    ax_z.set_title(f'p={p}', color=col, fontsize=10)\n",
    "    ax_z.set_xlim(-1.3, 1.3); ax_z.set_ylim(-1.3, 1.3)\n",
    "    ax_z.set_aspect('equal')\n",
    "\n",
    "    # Impulzusválasz\n",
    "    ax_h = axes[1, i]\n",
    "    h_k = p ** k\n",
    "    h_k_clipped = np.clip(h_k, -20, 20)\n",
    "    stab = 'STABIL' if abs(p) < 1 else ('MARGINÁLIS' if abs(p) == 1 else 'INSTABIL')\n",
    "    ax_h.stem(k[:35], h_k_clipped[:35], linefmt=col, markerfmt='o', basefmt='#2a3a5c')\n",
    "    ax_h.set_title(f'{stab}', color=col, fontsize=9)\n",
    "    ax_h.set_xlabel('k')\n",
    "\n",
    "plt.suptitle('Pólus-mozgatás a z-síkon → stabilitás', fontsize=13, color='#d0e0f0')\n",
    "plt.tight_layout(); plt.show()\n",
    "print(\"✅ |p| < 1 → stabil (csökkenő)\")\n",
    "print(\"   |p| = 1 → marginális (állandó)\")\n",
    "print(\"   |p| > 1 → INSTABIL (növekvő)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70ec3fe6",
   "metadata": {},
   "source": [
    "---\n",
    "## 20. feladat — Összefoglaló: az e^{jωt} az egész jelfeldolgozás kulcsa\n",
    "\n",
    "**Feladat:** Mutasd meg egyetlen ábrán, hogyan kapcsolódik össze:\n",
    "1. Komplex exponenciális → Euler\n",
    "2. Fourier-transzformáció\n",
    "3. Laplace (s-sík)\n",
    "4. z-transzformáció (z-sík)\n",
    "5. Frekvenciaválasz (Bode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b21ac294",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(16, 12))\n",
    "\n",
    "# 1. Euler-formula — forgó vektor\n",
    "ax1 = fig.add_subplot(3, 3, 1)\n",
    "theta = np.linspace(0, 2*np.pi, 100)\n",
    "ax1.plot(np.cos(theta), np.sin(theta), '--', color='#a78bfa', linewidth=1, alpha=0.3)\n",
    "t_anim = np.linspace(0, 2*np.pi, 20)\n",
    "for i, ta in enumerate(t_anim):\n",
    "    alpha = 0.1 + 0.9 * i / len(t_anim)\n",
    "    ax1.plot([0, np.cos(ta)], [0, np.sin(ta)], color='#a78bfa', alpha=alpha, linewidth=1)\n",
    "ax1.plot(np.cos(t_anim[-1]), np.sin(t_anim[-1]), 'o', color='#d946ef', markersize=8)\n",
    "ax1.set_title('① Euler: e^{jωt}', fontsize=10, color='#a78bfa')\n",
    "ax1.set_aspect('equal'); ax1.set_xlim(-1.4, 1.4); ax1.set_ylim(-1.4, 1.4)\n",
    "\n",
    "# 2. cos + sin = vetületek\n",
    "ax2 = fig.add_subplot(3, 3, 2)\n",
    "t = np.linspace(0, 3, 300)\n",
    "ax2.plot(t, np.cos(omega1*t), color='#38bdf8', linewidth=2, label='cos(ωt)')\n",
    "ax2.plot(t, np.sin(omega1*t), color='#ec4899', linewidth=2, label='sin(ωt)')\n",
    "ax2.set_title('② cos & sin = árnyékok', fontsize=10, color='#38bdf8')\n",
    "ax2.legend(fontsize=7)\n",
    "\n",
    "# 3. Sajátfüggvény\n",
    "ax3 = fig.add_subplot(3, 3, 3)\n",
    "H_jw = 1 / (1j*omega1 + sigma1)\n",
    "ax3.plot(t, np.cos(omega1*t), color='#38bdf8', linewidth=1, alpha=0.5, label='be')\n",
    "ax3.plot(t, abs(H_jw)*np.cos(omega1*t+np.angle(H_jw)), color='#22c55e', linewidth=2, label='ki')\n",
    "ax3.set_title('③ Sajátfv: H(jω)·e^{jωt}', fontsize=10, color='#22c55e')\n",
    "ax3.legend(fontsize=7)\n",
    "\n",
    "# 4. Fourier-spektrum\n",
    "ax4 = fig.add_subplot(3, 3, 4)\n",
    "x_sig = np.cos(f1*t) + 0.6*np.cos(f2*t)\n",
    "X = fft(x_sig)\n",
    "freqs = fftfreq(len(t), t[1]-t[0])\n",
    "mask = (freqs >= 0) & (freqs*2*np.pi < 15)\n",
    "ax4.plot(freqs[mask]*2*np.pi, np.abs(X[mask])*t[1], color='#fbbf24', linewidth=2)\n",
    "ax4.set_title('④ Fourier: |X(jω)|', fontsize=10, color='#fbbf24')\n",
    "ax4.set_xlabel('ω')\n",
    "\n",
    "# 5. s-sík (Laplace)\n",
    "ax5 = fig.add_subplot(3, 3, 5)\n",
    "ax5.axhline(0, color='#2a3a5c'); ax5.axvline(0, color='#38bdf8', linewidth=2, alpha=0.3)\n",
    "ax5.fill_betweenx([-6, 6], -5, 0, color='#22c55e', alpha=0.03)\n",
    "ax5.plot(-sigma1, omega1, 'x', color='#f87171', markersize=12, markeredgewidth=3)\n",
    "ax5.plot(-sigma1, -omega1, 'x', color='#f87171', markersize=12, markeredgewidth=3)\n",
    "ax5.set_title('⑤ s-sík: pólusok', fontsize=10, color='#f87171')\n",
    "ax5.set_xlabel('σ'); ax5.set_ylabel('jω')\n",
    "ax5.set_xlim(-4, 2); ax5.set_ylim(-6, 6); ax5.set_aspect('equal')\n",
    "ax5.text(0.2, 5, '← Fourier', color='#38bdf8', fontsize=7)\n",
    "\n",
    "# 6. Bode\n",
    "ax6 = fig.add_subplot(3, 3, 6)\n",
    "w = np.logspace(-1, 2, 300)\n",
    "H = omega1 / (1j*w + omega1)\n",
    "ax6.semilogx(w, 20*np.log10(np.abs(H)), color='#ec4899', linewidth=2)\n",
    "ax6.axhline(-3, color='#f87171', linewidth=0.5, linestyle='--')\n",
    "ax6.set_title('⑥ Bode: amplitúdó', fontsize=10, color='#ec4899')\n",
    "ax6.set_ylabel('dB')\n",
    "\n",
    "# 7. z-sík\n",
    "ax7 = fig.add_subplot(3, 3, 7)\n",
    "ax7.plot(np.cos(theta), np.sin(theta), '--', color='#a78bfa', linewidth=1)\n",
    "ax7.axhline(0, color='#2a3a5c'); ax7.axvline(0, color='#2a3a5c')\n",
    "Ts = 0.1\n",
    "z_pole = np.exp((-sigma1 + 1j*omega1)*Ts)\n",
    "ax7.plot(z_pole.real, z_pole.imag, 'x', color='#d946ef', markersize=12, markeredgewidth=3)\n",
    "ax7.plot(z_pole.real, -z_pole.imag, 'x', color='#d946ef', markersize=12, markeredgewidth=3)\n",
    "ax7.set_title('⑦ z = e^{sTs}: z-sík', fontsize=10, color='#d946ef')\n",
    "ax7.set_aspect('equal'); ax7.set_xlim(-1.3, 1.3); ax7.set_ylim(-1.3, 1.3)\n",
    "\n",
    "# 8. Konvolúciós tétel\n",
    "ax8 = fig.add_subplot(3, 3, 8)\n",
    "ax8.text(0.5, 0.7, 'IDTARTOMÁNY', ha='center', va='center', fontsize=11, color='#38bdf8', transform=ax8.transAxes)\n",
    "ax8.text(0.5, 0.5, 'x * h = y', ha='center', va='center', fontsize=14, color='#fbbf24', transform=ax8.transAxes, fontweight='bold')\n",
    "ax8.text(0.5, 0.3, 'FREKVENCIA', ha='center', va='center', fontsize=11, color='#ec4899', transform=ax8.transAxes)\n",
    "ax8.text(0.5, 0.1, 'X · H = Y', ha='center', va='center', fontsize=14, color='#ec4899', transform=ax8.transAxes, fontweight='bold')\n",
    "ax8.set_title('⑧ Konvolúciós tétel', fontsize=10, color='#fbbf24')\n",
    "ax8.axis('off')\n",
    "\n",
    "# 9. Összefoglalás\n",
    "ax9 = fig.add_subplot(3, 3, 9)\n",
    "ax9.text(0.5, 0.85, 'MINDENT', ha='center', va='center', fontsize=16, color='#fbbf24', transform=ax9.transAxes, fontweight='bold')\n",
    "ax9.text(0.5, 0.65, 'az e^{jωt}', ha='center', va='center', fontsize=18, color='#a78bfa', transform=ax9.transAxes, fontweight='bold')\n",
    "ax9.text(0.5, 0.45, 'köt össze:', ha='center', va='center', fontsize=14, color='#fbbf24', transform=ax9.transAxes)\n",
    "ax9.text(0.5, 0.22, 'j = forgás  |  ω = sebesség  |  t = idő', ha='center', va='center', fontsize=10, color='#d0e0f0', transform=ax9.transAxes)\n",
    "ax9.text(0.5, 0.06, '→ együtt: a rezgés DNS-e', ha='center', va='center', fontsize=10, color='#22c55e', transform=ax9.transAxes)\n",
    "ax9.axis('off')\n",
    "ax9.set_title('⑨ A teljes kép', fontsize=10, color='#22c55e')\n",
    "\n",
    "plt.suptitle('Az e^{jωt} összekötő ereje — 9 perspektíva', fontsize=15, color='#d0e0f0', y=1.0)\n",
    "plt.tight_layout(); plt.show()\n",
    "print(\"✅ Az e^{jωt} = a jelfeldolgozás EGÉSZ épületének alapköve.\")\n",
    "print(\"   j adja a forgást, ω a sebességet, t az időt.\")\n",
    "print(\"   Belőle épül: Euler → Fourier → Laplace → z-transzf → Bode → szűrőtervezés → CNN\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b96b9fd6",
   "metadata": {},
   "source": [
    "---\n",
    "## 🎓 Összefoglalás\n",
    "\n",
    "Ezek a gyakorlatok lefedik a **Jelek és Rendszerek** kurzus teljes anyagát:\n",
    "\n",
    "| # | Téma | Kulcs-meglátás |\n",
    "|---|---|---|\n",
    "| 1-3 | Komplex exponenciális | e^{jωt} = forgás, Euler-formula |\n",
    "| 4 | σ hatása | σ<0: stabil, σ=0: Fourier, σ>0: instabil |\n",
    "| 5 | Sajátfüggvény | LTI + e^{jωt} → H(jω)·e^{jωt} |\n",
    "| 6 | Fourier = korreláció | X(jω) = vetítés e^{−jωt}-re |\n",
    "| 7 | Konvolúciós tétel | Idő * = Frekvencia × |\n",
    "| 8-9 | Laplace-pólusok | Pólusok → impulzusválasz |\n",
    "| 10 | Bode-diagram | |H(jω)| és ∠H(jω) log skálán |\n",
    "| 11 | z-transzformáció | Egységkör belseje = stabil |\n",
    "| 12 | FIR vs IIR | Véges vs végtelen impulzusválasz |\n",
    "| 13 | Chirp + matched filter | Impulzuskompresszió |\n",
    "| 14 | Határozatlansági elv | Δt·Δω ≥ ½, Gauss az optimális |\n",
    "| 15 | Parseval-tétel | Energia megmarad |\n",
    "| 16 | DFT felbontás | Δf = fs/N |\n",
    "| 17 | Mintakeresés | Konvolúció = korreláció |\n",
    "| 18 | Ablakfüggvények | Melléknyaláb vs főnyaláb |\n",
    "| 19 | z-sík stabilitás | |p| < 1 → stabil |\n",
    "| 20 | Összefoglaló | e^{jωt} = minden alapja |\n",
    "\n",
    "> *Született: 1973.10.24. — Miskolci Egyetem*\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
