diff --git a/notebooks/Validacao_Wavelet_vs_BPSK.ipynb b/notebooks/Validacao_Wavelet_vs_BPSK.ipynb new file mode 100644 index 0000000..d4173c2 --- /dev/null +++ b/notebooks/Validacao_Wavelet_vs_BPSK.ipynb @@ -0,0 +1,2216 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Codificação energética eficiente para rede de sensores sem fio\n", + "\n", + "_Fernando Matheus do Nascimento Dantas_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objetivo\n", + "\n", + "* Apresentar uma comparação qualitativa entre consumos dos esquema de BPSK e com codificação Wavelet\n", + "\n", + "* O contexto é comunicação entre sensores Wireless\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from scipy.special import erfc\n", + "import matplotlib.pyplot as plt\n", + "plt.style.use('seaborn-ticks')\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Transmissão BPSK" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A seguir, estão definidas as funções utilizadas, respectivamente, para a pseudo-fonte, modulação e demodulação do esquema BPSK." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "SYMBOLS = [-1, 1]\n", + "\n", + "def bpsk_modulate(N):\n", + " return np.random.choice(SYMBOLS, int(N))\n", + "\n", + "def bpsk_demodulate(transmitted):\n", + " demodulated = np.ones(transmitted.shape) * -1\n", + " demodulated[transmitted >= 0] = 1\n", + " return demodulated" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Transmissão BPSK" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A probabilidade de erro calculada para o esquema BPSK é\n", + "\n", + "$$P_e = \\dfrac{1}{2}\\text{erfc}\\left(\\sqrt{\\frac{E_b}{N_0}}\\right)$$" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": {}, + "outputs": [], + "source": [ + "N = 100000\n", + "EbNo = np.arange(0, 10, 1)\n", + "EbNo_linear = 10 ** (EbNo / 10)\n", + "No = 1 / EbNo_linear\n", + "sigma = np.sqrt(No / 2)\n", + "pe_bpsk_theoretical = 0.5 * erfc(np.sqrt(EbNo_linear))\n", + "\n", + "modulated = bpsk_modulate(N)\n", + "\n", + "pe_bpsk = np.zeros(len(EbNo))\n", + "for i in range(len(EbNo)):\n", + " noise = np.random.normal(0, sigma[i], N)\n", + " transmitted = modulated + noise\n", + " demodulated = bpsk_demodulate(transmitted)\n", + " pe_bpsk[i] = np.average(modulated != demodulated)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Validação da transmissão BPSK" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A média da diferença entre a curva teórica e a simulada é apresentada, como maneira de mensurar a qualidade da simulação. \n", + "\n", + "Note que o valor resultante é praticamente desprezível." + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "O erro médio é 5.9e-05\n" + ] + } + ], + "source": [ + "error = np.average(pe_bpsk_theoretical - pe_bpsk)\n", + "\n", + "print(f'O erro médio é {error:.2g}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Transmissão com Codificação Wavelet\n", + "\n", + "A seguinte classe é proposta para lidar com a codificação Wavelet:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "class Wavelet:\n", + " def __init__(self, m, g):\n", + " self.m = m\n", + " self.g = g\n", + " self.mg = m * g\n", + " self.A = None\n", + " self.mcw = None\n", + "\n", + " def _allocate_a_matrix(self):\n", + " if self.A is None:\n", + " self.A = np.zeros((self.m, self.mg))\n", + "\n", + " def _get_raw_lines(self, file, type=float):\n", + " with open(file, 'r') as file:\n", + " flatten = [type(l) for l in file.readlines()]\n", + " size = int(np.size(flatten))\n", + " step = int(size / self.m)\n", + " for i in np.arange(0, size, step):\n", + " yield flatten[i: i + step]\n", + "\n", + " def _set_a_coefficients(self, file):\n", + " self._allocate_a_matrix()\n", + " lines = self._get_raw_lines(file)\n", + " for i in range(self.m):\n", + " self.A[i] = next(lines)\n", + "\n", + " def _allocate_mcw(self, message_length):\n", + " if self.mcw is None:\n", + " self.mcw = np.zeros((self.m, message_length + self.mg - self.m))\n", + "\n", + " def _displace_mcw(self, pad):\n", + " self.mcw = np.roll(self.mcw, pad)\n", + "\n", + " def _get_encoded_model(self):\n", + " return np.zeros((self.mcw.shape[1],))\n", + "\n", + " def mcw_from_coefficients(self, file, message_length):\n", + " self._set_a_coefficients(file)\n", + " self._allocate_mcw(message_length)\n", + " self.mcw[:self.m, :self.mg] = self.A\n", + "\n", + " def encode(self, message):\n", + " encoded = self._get_encoded_model()\n", + " mcw = np.copy(self.mcw)\n", + " for i in range(0, np.size(message), self.m):\n", + " encoded += np.matmul(message[i: i + self.m], mcw)\n", + " mcw = np.roll(mcw, self.m)\n", + " return encoded\n", + "\n", + " def _get_decoded_model(self):\n", + " return np.zeros((self.mcw.shape[1] - self.mg + self.m,))\n", + "\n", + " def decode(self, encoded):\n", + " decoded = self._get_decoded_model()\n", + " mcw = np.copy(self.mcw)\n", + " for i in range(np.size(decoded)):\n", + " if i and i % self.m == 0:\n", + " mcw = np.roll(mcw, self.m)\n", + " decoded[i] = np.dot(mcw[i % self.m], encoded)\n", + " return decoded" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Validação (prática) da codificação Wavelet\n", + "\n", + "A validação mostrada aqui é relativamente mais pragmática que a do esquema BPSK, que considera a curva teórica. Será considerada a codificação e decodificação de uma palavra de 10000 símbolos (-1 ou +1), na ausência de ruído. Constatar-se-á que o resultado da decodificação será exatamente igual ao da mensagem transmitida, o que, para efeitos práticos, denota que a codificação e decodificação funcionam corretamente." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "message = np.random.choice([-1, 1], 10000)\n", + "N = np.size(message)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "O objeto `Wavelet(m=2, g=64)` simboliza um codificador/decodificador wavelet com posto 2 e gênero 64." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "wavelet = Wavelet(m=2, g=64)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A Matriz de Codificação Wavelet utilizada é carregada em `wavelet` por meio do método `wavelet.mcw_from_coefficients(file)`, em que `file` é um arquivo de texto que contém os coeficientes da MCW. O sentido de leitura do `.txt` é tal que as linhas da MCW são preenchidas uma a uma, da esquerda para direita, até que não haja mais elementos a serem lidos." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "file = '../mcw2_128.txt'\n", + "wavelet.mcw_from_coefficients(file, N)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pode-se realizar, agora, a codificação e decodificação através dos métodos `encode` e `decode`." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "encoded = wavelet.encode(message)\n", + "decoded = wavelet.decode(encoded)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Verifica-se que a magnitude de todos os símbolos decodificados é $mg$. `set`, aqui, remove todos os elementos repetidos de `decoded`; `{wavelet.mg}` é um `set` com cardinalidade 1 (um), cujo único elemento é `wavelet.mg = 128`." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "set(np.abs(decoded)) == {wavelet.mg}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Limita-se os valores de `decoded` aos símbolos originais transmitidos ($-mg \\Rightarrow -1, +mg \\Rightarrow +1$)." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "decoded[decoded == wavelet.mg] = 1\n", + "decoded[decoded == -wavelet.mg] = -1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finalmente, verifica-se que `decoded` é **igual** a `message` (naturalmente, pois não houve interferência de qualquer ruído durante o processo)." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.array_equal(decoded, message)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Transmissão com codificação wavelet" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A informação a ser transmitida será a mesma da codificação BPSK, contida em `modulated`, já definida na seção de simulação BPSK.\n", + "\n", + "Os símbolos $y_n$ serão modulados por uma constelação ASK, com $mg+1$ pontos. \n", + "\n", + "O canal está sujeito, assim como no caso BPSK, a um ruído aditivo gaussiano de média nula e densidade espectral de potência igual a $N_0/2$, de tal maneira que os símbolos recebidos no decodificador serão $\\text{Re}\\{y_n + \\mathbf{n}_n\\}$, em que $\\mathbf{n}_n$ é um número complexo composto por variáveis aleatórias Gaussianas independentes e identicamente distribuídas com média nula e variância $N_0/2$.\n", + "\n", + "A densidade espectral de potência do ruído é $N_0=mg\\cdot 10^{-0.1\\left(\\frac{E_b}{N_0}\\right) \\text{ dB}}$" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [], + "source": [ + "EbNo = np.arange(0, 10, 1)\n", + "No = wavelet.mg * 10 ** (-EbNo / 10)\n", + "sigma = np.sqrt(No / 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [], + "source": [ + "wavelet = Wavelet(m=2, g=64)\n", + "wavelet.mcw_from_coefficients('../mcw2_128.txt', np.size(modulated))" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [], + "source": [ + "encoded = wavelet.encode(modulated)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`alphabet` são os possíveis símbolos de $y_n$." + ] + }, + { + "cell_type": "code", + "execution_count": 160, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cardinalidade de alphabet = mg + 1 = 129\n" + ] + } + ], + "source": [ + "alphabet = np.array([-wavelet.mg + 2 * k for k in range(wavelet.mg + 1)])\n", + "\n", + "print(f'Cardinalidade de alphabet = mg + 1 = {len(alphabet)}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`ask_demodulate` demodula os símbolos que chegam ao decodificador utilizando os símbolos definidos por `alphabet`." + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": {}, + "outputs": [], + "source": [ + "def ask_demodulate(transmitted):\n", + " indices = np.abs(np.subtract.outer(alphabet, transmitted)).argmin(0)\n", + " return np.asarray([alphabet[i] for i in indices])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Loop principal.** Estimação da probabilidade de erro _vs._ $Eb/N_0$." + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iteração 0/9\n", + "\tpe = 0.08021\n", + "Iteração 1/9\n", + "\tpe = 0.0574\n", + "Iteração 2/9\n", + "\tpe = 0.03876\n", + "Iteração 3/9\n", + "\tpe = 0.02469\n", + "Iteração 4/9\n", + "\tpe = 0.01358\n", + "Iteração 5/9\n", + "\tpe = 0.00644\n", + "Iteração 6/9\n", + "\tpe = 0.00266\n", + "Iteração 7/9\n", + "\tpe = 0.00092\n", + "Iteração 8/9\n", + "\tpe = 0.00027\n", + "Iteração 9/9\n", + "\tpe = 4e-05\n" + ] + } + ], + "source": [ + "pe_wavelet = np.zeros(len(EbNo))\n", + "\n", + "for i in range(len(EbNo)):\n", + " transmitted = np.random.normal(encoded, sigma[i], np.size(encoded))\n", + " demodulated = ask_demodulate(transmitted)\n", + " decoded = wavelet.decode(demodulated) / wavelet.mg\n", + " pe_wavelet[i] = np.average(np.sign(decoded) != modulated)\n", + " print(f\"Iteração {i}/{len(EbNo) - 1}\")\n", + " print(f\"\\tpe_wavelet = {pe_wavelet[i]}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Resultados" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Curvas $BER \\times E_b/N_0$" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support. ' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " fig.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
');\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0))\n", + "plt.title(\"Energia por bit útil\")\n", + "plt.ylabel(\"Energia/bit (J/bit)\")\n", + "plt.xlabel(\"$E_b/N_0$ (db)\")\n", + "plt.plot(EbNo, Eb_wavelet, 'x--', label=\"PAM-MCW 2x64\")\n", + "plt.plot(EbNo, Eb_bpsk, 'r', label=\"BPSK\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusão\n", + "\n", + "As curvas plotadas mostram que, para o esquema BPSK, o desempenho da codificação Wavelet não alterou significativamente a eficiência da transmissão. As probabilidades de erro para os dois esquemas mostraram-se muito próximas e, consequentemente, os consumos energéticos." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}