diff options
author | jaseg <git-bigdata-wsl-arch@jaseg.de> | 2021-04-09 18:38:02 +0200 |
---|---|---|
committer | jaseg <git-bigdata-wsl-arch@jaseg.de> | 2021-04-09 18:38:57 +0200 |
commit | 50998fcfb916ae251309bd4b464f2c122e8cb30d (patch) | |
tree | 4ecf7a7443b75ab51c4dc0c0fc9289342dc7d6a0 /lab-windows/dsss_experiments.ipynb | |
parent | 312fee491cfab436d52db4b6265107e20f3e1293 (diff) | |
download | master-thesis-50998fcfb916ae251309bd4b464f2c122e8cb30d.tar.gz master-thesis-50998fcfb916ae251309bd4b464f2c122e8cb30d.tar.bz2 master-thesis-50998fcfb916ae251309bd4b464f2c122e8cb30d.zip |
Repo re-org
Diffstat (limited to 'lab-windows/dsss_experiments.ipynb')
-rw-r--r-- | lab-windows/dsss_experiments.ipynb | 946 |
1 files changed, 0 insertions, 946 deletions
diff --git a/lab-windows/dsss_experiments.ipynb b/lab-windows/dsss_experiments.ipynb deleted file mode 100644 index 8019081..0000000 --- a/lab-windows/dsss_experiments.ipynb +++ /dev/null @@ -1,946 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from matplotlib import pyplot as plt\n", - "import numpy as np\n", - "from scipy import signal as sig\n", - "import struct\n", - "import random\n", - "import ipywidgets\n", - "import itertools\n", - "\n", - "import colorednoise\n", - "\n", - "np.set_printoptions(linewidth=240)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib widget" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "sampling_rate = 10 # sp/s" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "#colorednoise.powerlaw_psd_gaussian(1, int(1e4))" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# From https://github.com/mubeta06/python/blob/master/signal_processing/sp/gold.py\n", - "preferred_pairs = {5:[[2],[1,2,3]], 6:[[5],[1,4,5]], 7:[[4],[4,5,6]],\n", - " 8:[[1,2,3,6,7],[1,2,7]], 9:[[5],[3,5,6]], \n", - " 10:[[2,5,9],[3,4,6,8,9]], 11:[[9],[3,6,9]]}\n", - "\n", - "def gen_gold(seq1, seq2):\n", - " print(seq1.shape, seq2.shape)\n", - " gold = [seq1, seq2]\n", - " for shift in range(len(seq1)):\n", - " gold.append(seq1 ^ np.roll(seq2, -shift))\n", - " return gold\n", - "\n", - "def gold(n):\n", - " n = int(n)\n", - " if not n in preferred_pairs:\n", - " raise KeyError('preferred pairs for %s bits unknown' % str(n))\n", - " t0, t1 = preferred_pairs[n]\n", - " (seq0, _st0), (seq1, _st1) = sig.max_len_seq(n, taps=t0), sig.max_len_seq(n, taps=t1)\n", - " return gen_gold(seq0, seq1)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5081f9508a894fcf810e2d9c92c24a3e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n" - ] - }, - { - "data": { - "text/plain": [ - "<matplotlib.image.AxesImage at 0x7ff8d9616610>" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "ax.matshow(gold(5))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "def modulate(data, nbits=5):\n", - " # 0, 1 -> -1, 1\n", - " mask = np.array(gold(nbits))*2 - 1\n", - " \n", - " sel = mask[data>>1]\n", - " data_lsb_centered = ((data&1)*2 - 1)\n", - "\n", - " return (np.multiply(sel, np.tile(data_lsb_centered, (2**nbits-1, 1)).T).flatten() + 1) // 2" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n" - ] - }, - { - "data": { - "text/plain": [ - "array([-1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1,\n", - " 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1,\n", - " 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1,\n", - " 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1,\n", - " -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1,\n", - " 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1,\n", - " 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1,\n", - " -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1,\n", - " -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1])" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "data = np.array(list(range(16)))\n", - "\n", - "mask = np.array(gold(5))*2 - 1\n", - " \n", - "sel = mask[data>>1]\n", - "data_lsb_centered = ((data&1)*2 - 1)\n", - "mask.shape, data.shape, sel.shape\n", - "\n", - "#fig, ax = plt.subplots()\n", - "#ax.plot(\n", - "np.multiply(sel, np.tile(data_lsb_centered, (2**5-1, 1)).T).flatten()" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "def correlate(sequence, nbits=5, decimation=1, mask_filter=lambda x: x):\n", - " mask = np.tile(np.array(gold(nbits))[:,:,np.newaxis]*2 - 1, (1, 1, decimation)).reshape((2**nbits + 1, (2**nbits-1) * decimation))\n", - "\n", - " sequence -= np.mean(sequence)\n", - " \n", - " return np.array([np.correlate(sequence, row, mode='full') for row in mask])" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n", - "(31,) (31,)\n", - "shapes (1240,) (1240,)\n", - "(31,) (31,)\n", - "mask (33, 310)\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ec8de5680ba541938b7d1843b841c327", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n" - ] - }, - { - "data": { - "text/plain": [ - "<matplotlib.image.AxesImage at 0x7ff8d955afa0>" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "nbits = 5\n", - "decimation = 10\n", - "\n", - "foo = np.repeat(modulate(np.array(list(range(4))), nbits).astype(float), decimation)\n", - "bar = np.repeat(modulate(np.array(list(range(4))), nbits) * 2.0 - 1, decimation) * 1e-3\n", - "print('shapes', foo.shape, bar.shape)\n", - "\n", - "mask = np.tile(np.array(gold(nbits))[:,:,np.newaxis]*2 - 1, (1, 1, decimation)).reshape((2**nbits + 1, (2**nbits-1) * decimation))\n", - "print('mask', mask.shape)\n", - "\n", - "fig, (ax1, ax2) = plt.subplots(2, figsize=(16, 5))\n", - "fig.tight_layout()\n", - "corr_m = np.array([np.correlate(foo, row, mode='full') for row in mask])\n", - "#corr_m = np.array([row for row in mask])\n", - "ax1.matshow(corr_m, aspect='auto')\n", - "#ax.matshow(foo.reshape(32, 31)[::2,:])\n", - "ax2.matshow(correlate(bar, decimation=decimation), aspect='auto')" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "bb32b5050ee14ddc8eb64697a8eb774b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n", - "(31,) (31,)\n" - ] - }, - { - "data": { - "text/plain": [ - "<matplotlib.image.AxesImage at 0x7ff8d8eb9e20>" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "decimation = 10\n", - "\n", - "fig, (ax1, ax2) = plt.subplots(2, figsize=(12, 5))\n", - "fig.tight_layout()\n", - "\n", - "#mask = np.tile(np.array(gold(nbits))[:,:,np.newaxis]*2 - 1, (1, 1, decimation)).reshape((2**nbits + 1, (2**nbits-1) * decimation))\n", - "#mask_stretched = np.tile(np.array(gold(nbits))[:,:,np.newaxis]*2 - 1, (1, 1, 1)).reshape((2**nbits + 1, (2**nbits-1) * 1))\n", - "\n", - "#ax1.matshow(mask)\n", - "#ax2.matshow(mask_stretched, aspect='auto')\n", - "\n", - "foo = np.repeat(modulate(np.array(list(range(4)))).astype(float), 1).reshape((4, 31))\n", - "foo_stretched = np.repeat(modulate(np.array(list(range(4)))).astype(float), 10).reshape(4, 310)\n", - "\n", - "ax1.matshow(foo)\n", - "ax2.matshow(foo_stretched, aspect='auto')" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "48b3ae259e8046a5b90a82c4e80bab2e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(31,) (31,)\n", - "(31,) (31,)\n" - ] - }, - { - "data": { - "text/plain": [ - "(2.0, 1.0121324810255907)" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "decimation = 10\n", - "signal_amplitude = 2.0\n", - "nbits = 5\n", - "\n", - "foo = np.repeat(modulate(np.array([0, 1, 0, 0, 1, 1, 1, 0]), nbits) * 2.0 - 1, decimation) * signal_amplitude\n", - "noise = colorednoise.powerlaw_psd_gaussian(1, len(foo))\n", - "\n", - "sosh = sig.butter(4, 0.01, btype='highpass', output='sos', fs=decimation)\n", - "sosl = sig.butter(6, 1.0, btype='lowpass', output='sos', fs=decimation)\n", - "filtered = sig.sosfilt(sosh, sig.sosfilt(sosl, foo + noise))\n", - "#filtered = sig.sosfilt(sosh, foo + noise)\n", - "\n", - "fig, ((ax1, ax3), (ax2, ax4)) = plt.subplots(2, 2, figsize=(16, 9))\n", - "fig.tight_layout()\n", - "\n", - "ax1.plot(foo + noise)\n", - "ax1.plot(foo)\n", - "ax1.set_title('raw')\n", - "\n", - "ax2.plot(filtered)\n", - "ax2.plot(foo)\n", - "ax2.set_title('filtered')\n", - "\n", - "ax3.plot(correlate(foo + noise, nbits=nbits, decimation=decimation))\n", - "ax3.set_title('corr raw')\n", - " \n", - "ax3.grid()\n", - "\n", - "ax4.plot(correlate(filtered, nbits=nbits, decimation=decimation))\n", - "ax4.set_title('corr filtered')\n", - "ax4.grid()\n", - "\n", - "rms = lambda x: np.sqrt(np.mean(np.square(x)))\n", - "rms(foo), rms(noise)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "mean: 49.98625\n" - ] - } - ], - "source": [ - "with open('/mnt/c/Users/jaseg/shared/raw_freq.bin', 'rb') as f:\n", - " mains_noise = np.copy(np.frombuffer(f.read(), dtype='float32'))\n", - " print('mean:', np.mean(mains_noise))\n", - " mains_noise -= np.mean(mains_noise)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(63,) (63,)\n", - "(63,) (63,)\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "73f4caf6a80f448183c41b711412a471", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "(0.0020000000000000005, 0.014544699)" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "decimation = 10\n", - "signal_amplitude = 2.0e-3\n", - "nbits = 6\n", - "\n", - "#test_data = np.random.randint(0, 2, 100)\n", - "#test_data = np.array([0, 1, 0, 0, 1, 1, 1, 0])\n", - "test_data = np.random.RandomState(seed=0xcbb3b8cf).randint(0, 2 * (2**nbits), 128)\n", - "#test_data = np.random.RandomState(seed=0).randint(0, 8, 64)\n", - "#test_data = np.array(list(range(8)) * 8)\n", - "#test_data = np.array([0, 1] * 32)\n", - "#test_data = np.array(list(range(64)))\n", - "\n", - "foo = np.repeat(modulate(test_data, nbits) * 2.0 - 1, decimation) * signal_amplitude\n", - "noise = np.resize(mains_noise, len(foo))\n", - "#noise = 0\n", - "\n", - "sosh = sig.butter(3, 0.01, btype='highpass', output='sos', fs=decimation)\n", - "sosl = sig.butter(3, 0.8, btype='lowpass', output='sos', fs=decimation)\n", - "#filtered = sig.sosfilt(sosh, sig.sosfilt(sosl, foo + noise))\n", - "filtered = sig.sosfilt(sosh, foo + noise)\n", - "\n", - "cor1 = correlate(foo + noise, nbits=nbits, decimation=decimation)\n", - "#cor2 = correlate(filtered, nbits=nbits, decimation=decimation)\n", - "\n", - "#cor2_pe = correlate(filtered, nbits=nbits, decimation=decimation, mask_filter=lambda mask: sig.sosfilt(sosh, sig.sosfiltfilt(sosl, mask)))\n", - "\n", - "sosn = sig.butter(12, 4, btype='highpass', output='sos', fs=decimation)\n", - "#cor1_flt = sig.sosfilt(sosn, cor1)\n", - "#cor2_flt = sig.sosfilt(sosn, cor2)\n", - "#cor1_flt = cor1[1:] - cor1[:-1]\n", - "#cor2_flt = cor2[1:] - cor2[:-1]\n", - "\n", - "fig, ((ax1, ax3), (ax2, ax4)) = plt.subplots(2, 2, figsize=(16, 9))\n", - "fig.tight_layout()\n", - "\n", - "ax1.plot(foo + noise)\n", - "ax1.plot(foo)\n", - "ax1.set_title('raw')\n", - "ax1.grid(axis='y')\n", - "\n", - "ax2.plot(filtered)\n", - "ax2.plot(foo)\n", - "ax2.set_title('filtered')\n", - "ax2.grid(axis='y')\n", - "\n", - "for i in range(0, len(foo) + 1, decimation*(2**nbits - 1)):\n", - " ax1.axvline(i, color='gray', alpha=0.5, lw=1)\n", - " ax2.axvline(i, color='gray', alpha=0.5, lw=1)\n", - "\n", - "for i, (color, trace) in enumerate(zip(plt.cm.winter(np.linspace(0, 1, cor1.shape[0])), cor1.T)):\n", - " if i%3 == 0:\n", - " ax3.plot(trace + 0.5 * i, alpha=1.0, color=color)\n", - "ax3.set_title('corr raw')\n", - "ax3.grid()\n", - "\n", - "#ax4.plot(cor2[:4].T)\n", - "#ax4.set_title('corr filtered')\n", - "#ax4.grid()\n", - "ax4.matshow(cor1, aspect='auto')\n", - "\n", - "#ax5.plot(cor1_flt)\n", - "#ax5.set_title('corr raw (highpass)')\n", - "#ax5.grid()\n", - "\n", - "#ax6.plot(cor2_flt)\n", - "#ax6.set_title('corr filtered (highpass)')\n", - "#ax6.grid()\n", - "\n", - "#ax6.plot(cor2_pe[:4].T)\n", - "#ax6.set_title('corr filtered w/ mask preemphasis')\n", - "#ax6.grid()\n", - "\n", - "rms = lambda x: np.sqrt(np.mean(np.square(x)))\n", - "rms(foo), rms(noise)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9fa8fa6a6837412da95630c634a12e21", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(63,) (63,)\n" - ] - }, - { - "data": { - "text/plain": [ - "[<matplotlib.lines.Line2D at 0x7ff8ad6f3b50>]" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "seq = np.repeat(gold(6)[29]*2 -1, decimation)\n", - "sosh = sig.butter(3, 0.01, btype='highpass', output='sos', fs=decimation)\n", - "sosl = sig.butter(3, 0.8, btype='lowpass', output='sos', fs=decimation)\n", - "seq_filtered = sig.sosfilt(sosh, sig.sosfiltfilt(sosl, seq))\n", - "#seq_filtered = sig.sosfilt(sosh, seq)\n", - "\n", - "ax.plot(seq)\n", - "ax.plot(seq_filtered)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "854dec05e45340ae91cf271b2facd7ed", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(63,) (63,)\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'cor2_pe' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m<ipython-input-24-f158dfc14cca>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0msosh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbutter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0.1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'highpass'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moutput\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'sos'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdecimation\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0msosl\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbutter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0.8\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'lowpass'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moutput\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'sos'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdecimation\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mcor2_pe_flt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msosfilt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msosh\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcor2_pe\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0mcor2_pe_flt2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msosfilt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msosh\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msosfiltfilt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msosl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcor2_pe\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'cor2_pe' is not defined" - ] - } - ], - "source": [ - "fig, axs = plt.subplots(3, 1, figsize=(9, 7), sharex=True)\n", - "fig.tight_layout()\n", - "axs = axs.flatten()\n", - "for ax in axs:\n", - " ax.grid()\n", - "\n", - "seq = np.repeat(gold(6)[29]*2 -1, decimation)\n", - "sosh = sig.butter(3, 0.1, btype='highpass', output='sos', fs=decimation)\n", - "sosl = sig.butter(3, 0.8, btype='lowpass', output='sos', fs=decimation)\n", - "cor2_pe_flt = sig.sosfilt(sosh, cor2_pe)\n", - "cor2_pe_flt2 = sig.sosfilt(sosh, sig.sosfiltfilt(sosl, cor2_pe))\n", - "\n", - "axs[0].plot(cor2_pe)\n", - "axs[1].plot(cor2_pe_flt)\n", - "axs[2].plot(cor2_pe_flt2)\n", - "\n", - "#for idx in np.where(np.abs(cor2_pe_flt2) > 0.5)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b3f68635d3ad4863b990c0b6e742840b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "[<matplotlib.lines.Line2D at 0x7ff8a9b7a820>]" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, ax = plt.subplots()\n", - "nonlinear_distance = lambda x: 100**(2*np.abs(0.5-x%1)) / (np.abs(x)+3)**2\n", - "x = np.linspace(-1.5, 5.5, 10000)\n", - "ax.plot(x, nonlinear_distance(x))" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a6c4ef5b68a745b9963d3407df2e03fc", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cor_an (65, 81269)\n", - "cwt_res (65, 81269)\n", - "th (65, 81269)\n", - "[((65,), (65,)), ((65,), (65,)), ((65,), (65,)), ((65,), (65,)), ((65,), (65,))]\n", - "peaks: 1852\n", - "avg_peak 1.6610203317347632\n", - "skipped 3 symbols at 42209.0\n", - "decoding [ref|dec]:\n", - " 10| 10 ✔ 69| 69 ✔ 124|124 ✔ 102|102 ✔ 2| 2 ✔ 3| 3 ✔ 78| 78 ✔ 29| 29 ✔ \n", - "122|123 ✘ 73| 73 ✔ 98| 98 ✔ 34| 34 ✔ -1| -1 ✔ 97| 97 ✔ 7| 7 ✔ 97| 97 ✔ \n", - " 86| 86 ✔ 120|120 ✔ 95| 95 ✔ 90| 90 ✔ 49| 49 ✔ 89| 89 ✔ 83| 83 ✔ 19| 19 ✔ \n", - " 84| 84 ✔ 117|117 ✔ 92| 92 ✔ 119|119 ✔ 16| 16 ✔ 45| 45 ✔ 23| 23 ✔ 16| 16 ✔ \n", - "111|111 ✔ 9| 9 ✔ 89| 89 ✔ 18| 18 ✔ 36| 36 ✔ 2| 2 ✔ 115|115 ✔ 40| 40 ✔ \n", - "100|100 ✔ 105|105 ✔ 93| 93 ✔ 85| 85 ✔ 107|107 ✔ 90| 90 ✔ 62| 62 ✔ 116|116 ✔ \n", - " 42| 42 ✔ 123|123 ✔ 40| 40 ✔ -1| -1 ✔ 77| 77 ✔ 40| 40 ✔ 57| 57 ✔ 110|110 ✔ \n", - " 29| 29 ✔ 94| 94 ✔ 1| 1 ✔ 29| 29 ✔ 71| 71 ✔ 119|119 ✔ 15| 15 ✔ 115|115 ✔ \n", - "120| -1 70| -1 50| 50 ✔ 71| 71 ✔ 50| 50 ✔ 61| 61 ✔ 38| 38 ✔ 4| 4 ✔ \n", - " 3| 3 ✔ 124|124 ✔ 95| 95 ✔ 27| 27 ✔ 48| 48 ✔ 116|116 ✔ 3| 3 ✔ 63| 63 ✔ \n", - " 19| 19 ✔ 79| 79 ✔ 2| 2 ✔ 43| 43 ✔ 92| 92 ✔ 8| 8 ✔ 65| 65 ✔ 35| 35 ✔ \n", - " 30| 30 ✔ 73| 73 ✔ 73| 73 ✔ 38| 38 ✔ 58| 58 ✔ 49| 49 ✔ 45| 45 ✔ 58| 58 ✔ \n", - " 46| 46 ✔ 116|116 ✔ 101|101 ✔ 5| 5 ✔ 78| 78 ✔ 126|126 ✔ 105| 76 ✘ 108|108 ✔ \n", - " 59| 59 ✔ 46| 46 ✔ 27| 27 ✔ 14| 14 ✔ 57| 57 ✔ 81| 81 ✔ 3| 3 ✔ 9| 9 ✔ \n", - "126|126 ✔ 18| 55 ✘ 76| 76 ✔ 101|101 ✔ 124|124 ✔ 4| 4 ✔ 3| 3 ✔ 102|102 ✔ \n", - " 79| 79 ✔ 121|121 ✔ 103|103 ✔ 92| 92 ✔ 30| 30 ✔ 4| 4 ✔ 103|103 ✔ 59| 58 ✘ \n", - "Symbol error rate e=0.046875\n", - "maximum bitrate r=321.6796875 b/h\n" - ] - } - ], - "source": [ - "threshold_factor = 4.0\n", - "power_avg_width = 1024\n", - "max_lookahead = 6.5\n", - "\n", - "bit_period = (2**nbits) * decimation\n", - "peak_group_threshold = 0.1 * bit_period\n", - "\n", - "cor_an = cor1\n", - "\n", - "#fig, (ax1, ax2, ax3) = plt.subplots(3, figsize=(12, 12))\n", - "fig, (ax1, ax3) = plt.subplots(2, figsize=(12, 5))\n", - "fig.tight_layout()\n", - "\n", - "#ax1.matshow(sig.cwt(cor_an, sig.ricker, np.arange(1, 31)), aspect='auto')\n", - "\n", - "#for i in np.linspace(1, 10, 19):\n", - "# offx = 5*i\n", - "# ax2.plot(sig.cwt(cor_an, sig.ricker, [i]).flatten() + offx, color='red')\n", - "#\n", - "# ax2.text(-50, offx, f'{i:.1f}',\n", - "# horizontalalignment='right',\n", - "# verticalalignment='center',\n", - "# color='black')\n", - "#ax2.grid()\n", - "\n", - "ax3.grid()\n", - "print('cor_an', cor_an.shape)\n", - "\n", - "cwt_res = np.array([ sig.cwt(row, sig.ricker, [0.73 * decimation]).flatten() for row in cor_an ])\n", - "ax3.plot(cwt_res.T)\n", - "#def update(w = 1.0 * decimation):\n", - "# line.set_ydata(sig.cwt(cor_an, sig.ricker, [w]).flatten())\n", - "# fig.canvas.draw_idle()\n", - "#ipywidgets.interact(update)\n", - "\n", - "print('cwt_res', cwt_res.shape)\n", - "th = np.array([ np.convolve(np.abs(row), np.ones((power_avg_width,))/power_avg_width, mode='same') for row in cwt_res ])\n", - "ax1.plot(th.T)\n", - "print('th', th.shape)\n", - "\n", - "def compare_th(elem):\n", - " idx, (th, val) = elem\n", - " #print('compare_th:', th.shape, val.shape)\n", - " return np.any(np.abs(val) > th*threshold_factor)\n", - "\n", - "print([ (a.shape, b.shape) for a, b in zip(th.T, cwt_res.T) ][:5])\n", - "\n", - "peaks = [ list(group) for val, group in itertools.groupby(enumerate(zip(th.T, cwt_res.T)), compare_th) if val ]\n", - "print('peaks:', len(peaks))\n", - "peak_group = []\n", - "for group in peaks:\n", - " pos = np.mean([idx for idx, _val in group])\n", - " pol = np.mean([max(val.min(), val.max(), key=abs) for _idx, (_th, val) in group])\n", - " pol_idx = np.argmax(np.bincount([ np.argmax(np.abs(val)) for _idx, (_th, val) in group ]))\n", - " #print(f'group', pos, pol, pol_idx)\n", - " #for pol, (_idx, (_th, val)) in zip([max(val.min(), val.max(), key=abs) for _idx, (_th, val) in group], group):\n", - " # print(' ', pol, val)\n", - " ax3.axvline(pos, color='cyan', alpha=0.3)\n", - " \n", - " if not peak_group or pos - peak_group[-1][1] > peak_group_threshold:\n", - " if peak_group:\n", - " peak_pos = peak_group[-1][3]\n", - " ax3.axvline(peak_pos, color='red', alpha=0.6)\n", - " #ax3.text(peak_pos-20, 2.0, f'{0 if pol < 0 else 1}', horizontalalignment='right', verticalalignment='center', color='black')\n", - " \n", - " peak_group.append((pos, pos, pol, pos, pol_idx))\n", - " #ax3.axvline(pos, color='cyan', alpha=0.5)\n", - " \n", - " else:\n", - " group_start, last_pos, last_pol, peak_pos, last_pol_idx = peak_group[-1]\n", - " \n", - " if abs(pol) > abs(last_pol):\n", - " #ax3.axvline(pos, color='magenta', alpha=0.5)\n", - " peak_group[-1] = (group_start, pos, pol, pos, pol_idx)\n", - " else:\n", - " #ax3.axvline(pos, color='blue', alpha=0.5)\n", - " peak_group[-1] = (group_start, pos, last_pol, peak_pos, last_pol_idx)\n", - "\n", - "avg_peak = np.mean(np.abs(np.array([last_pol for _1, _2, last_pol, _3, _4 in peak_group])))\n", - "print('avg_peak', avg_peak)\n", - "\n", - "noprint = lambda *args, **kwargs: None\n", - "def mle_decode(peak_groups, print=print):\n", - " peak_groups = [ (pos, pol, idx) for _1, _2, pol, pos, idx in peak_groups ]\n", - " candidates = [ (0, [(pos, pol, idx)]) for pos, pol, idx in peak_groups if pos < bit_period*2.5 ]\n", - " \n", - " while candidates:\n", - " chain_candidates = []\n", - " for chain_score, chain in candidates:\n", - " pos, ampl, _idx = chain[-1]\n", - " score_fun = lambda pos, npos, npol: abs(npol)/avg_peak + nonlinear_distance((npos-pos)/bit_period)\n", - " next_candidates = sorted([ (score_fun(pos, npos, npol), npos, npol, nidx) for npos, npol, nidx in peak_groups if pos < npos < pos + bit_period*max_lookahead ], reverse=True)\n", - " \n", - " print(f' candidates for {pos}, {ampl}:')\n", - " for score, npos, npol, nidx in next_candidates:\n", - " print(f' {score:.4f} {npos:.2f} {npol:.2f} {nidx:.2f}')\n", - " \n", - " nch, cor_len = cor_an.shape\n", - " if cor_len - pos < 1.5*bit_period or not next_candidates:\n", - " score = sum(score_fun(opos, npos, npol) for (opos, _opol, _oidx), (npos, npol, _nidx) in zip(chain[:-1], chain[1:])) / len(chain)\n", - " yield score, chain\n", - " \n", - " else:\n", - " print('extending')\n", - " for score, npos, npol, nidx in next_candidates[:3]:\n", - " if score > 0.5:\n", - " new_chain_score = chain_score * 0.9 + score * 0.1\n", - " chain_candidates.append((new_chain_score, chain + [(npos, npol, nidx)]))\n", - " print('chain candidates:')\n", - " for score, chain in sorted(chain_candidates, reverse=True):\n", - " print(' ', [(score, [(f'{pos:.2f}', f'{pol:.2f}') for pos, pol, _idx in chain])])\n", - " candidates = [ (chain_score, chain) for chain_score, chain in sorted(chain_candidates, reverse=True)[:10] ]\n", - "\n", - "res = sorted(mle_decode(peak_group, print=noprint), reverse=True)\n", - "#for i, (score, chain) in enumerate(res):\n", - "# print(f'Chain {i}@{score:.4f}: {chain}')\n", - "(_score, chain), *_ = res\n", - "\n", - "def viz(chain):\n", - " last_pos = None\n", - " for pos, pol, nidx in chain:\n", - " if last_pos:\n", - " delta = int(round((pos - last_pos) / bit_period))\n", - " if delta > 1:\n", - " print(f'skipped {delta} symbols at {pos}')\n", - " for i in range(delta-1):\n", - " yield None\n", - " ax3.axvline(pos, color='blue', alpha=0.5)\n", - " decoded = nidx*2 + (0 if pol < 0 else 1)\n", - " yield decoded\n", - " ax3.text(pos-20, 0.0, f'{decoded}', horizontalalignment='right', verticalalignment='center', color='black')\n", - "\n", - " last_pos = pos\n", - "\n", - "decoded = list(viz(chain))\n", - "print('decoding [ref|dec]:')\n", - "failures = 0\n", - "for i, (ref, found) in enumerate(itertools.zip_longest(test_data, decoded)):\n", - " print(f'{ref or -1:>3d}|{found or -1:>3d} {\"✔\" if ref==found else \"✘\" if found else \" \"}', end=' ')\n", - " if ref != found:\n", - " failures += 1\n", - " if i%8 == 7:\n", - " print()\n", - "print(f'Symbol error rate e={failures/len(test_data)}')\n", - "print(f'maximum bitrate r={sampling_rate / decimation / (2**nbits) * nbits * (1 - failures/len(test_data)) * 3600} b/h')\n", - "#ax3.plot(th)" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "44d617eb7c5c416f96e16c9221c4fe96", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "ename": "NameError", - "evalue": "name 'cor2_pe_flt2' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m<ipython-input-30-968181501cb1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgrid\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0maxs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcor2_pe_flt2\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mcor2_pe_flt2\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcor2_pe_flt2\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mcor2_pe_flt2\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0.0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0maxs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconvolve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'full'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'cor2_pe_flt2' is not defined" - ] - } - ], - "source": [ - "fig, axs = plt.subplots(2, 1, figsize=(9, 7))\n", - "fig.tight_layout()\n", - "axs = axs.flatten()\n", - "for ax in axs:\n", - " ax.grid()\n", - " \n", - "axs[0].plot(cor2_pe_flt2[1::10] - cor2_pe_flt2[:-1:10])\n", - "a, b = cor2_pe_flt2[1::10] - cor2_pe_flt2[:-1:10], np.array([0.0, -0.5, 1.0, -0.5, 0.0])\n", - "axs[1].plot(np.convolve(a, b, mode='full'))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "labenv", - "language": "python", - "name": "labenv" - }, - "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.8.1" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} |