{ "cells": [ { "cell_type": "markdown", "id": "43a219ed", "metadata": {}, "source": [ "# `mcsm-benchs`: Benchmarking methods for signal detection" ] }, { "cell_type": "markdown", "id": "dc3f1ca1", "metadata": {}, "source": [ "In this notebook, we show how to benchmark signal detection methods using `mcsm-benchs`. We begin by importing a series of useful libraries." ] }, { "cell_type": "code", "execution_count": 21, "id": "04325818", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from numpy import pi as pi\n", "# import pandas as pd\n", "from matplotlib import pyplot as plt\n", "from mcsm_benchs.Benchmark import Benchmark\n", "from mcsm_benchs.ResultsInterpreter import ResultsInterpreter\n", "from mcsm_benchs.SignalBank import SignalBank\n", "from utils import get_stft" ] }, { "cell_type": "markdown", "id": "e346c281", "metadata": {}, "source": [ "## Creating a signal dictionary for the benchmark" ] }, { "cell_type": "markdown", "id": "25d44708", "metadata": {}, "source": [ "We then create a dictionary of signals to detect. As an example, let's use one signal composed of a linear chirp that spans half of the signal length using the `SignalBank` class." ] }, { "cell_type": "code", "execution_count": 22, "id": "c07d6f4f", "metadata": {}, "outputs": [ { "data": { "image/png": "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b5yzGt/PlhdB2kXY5Gd/9mdx4MCB8vjyl79cvva2t70Nf/d3f4dPf/rTuPfee/H444/jiiuuWMOrPbX0+308+9nPxoc//OGRr99888340Ic+hFtuuQX3338/2u02Lr74YiRJUp5z1VVX4aGHHsKdd96J22+/HV/60pfwpje96XR9hFPGib4bALjkkksaf5Y++clPNl7frN8NANx777249tpr8dWvfhV33nkn8jzHRRddhH6/X55zor9PQgi87GUvQ5Zl+MpXvoKPfvSjuO222/Dud797LT7SqrKc7wcA3vjGNzb+DN18883la6v2/agtzi/8wi+oa6+9tnwshFB79+5VN9100xpe1drwnve8Rz372c8e+drs7KzyPE99+tOfLp/713/9VwVA3XfffafpCtcOAOqzn/1s+VhKqXbv3q3+5E/+pHxudnZWBUGgPvnJTyqllPrud7+rAKivf/3r5Tn/8A//oBhj6ic/+clpu/ZTzfB3o5RSV199tbr88ssX/Zmt8t1YDh8+rACoe++9Vym1vL9Pf//3f6845+rgwYPlOR/5yEfU+Pi4StP09H6AU8zw96OUUv/hP/wH9Za3vGXRn1mt72dLR4Ins4tws/P9738fe/fuxZOf/GRcddVV2L9/PwDggQceQJ7nje/qGc94Bp74xCduye/qsccew8GDBxvfx8TEBM4///zy+7jvvvswOTmJ5z3veeU5F154ITjnuP/++0/7NZ9u7rnnHkxPT+PpT3863vzmN+PYsWPla1vtu5mbmwMATE1NAVje36f77rsP5513XsP56uKLL0a328VDDz10Gq/+1DP8/Vg+/vGPY8eOHTj33HNx4403YjAYlK+t1vezaRxjToaT2UW4mTn//PNx22234elPfzoOHDiA3//938eLXvQifOc738HBgwfh+z4mJycbP7Nr1y4cPHhwbS54DbGfedSfHfvawYMHMT093XjddV1MTU1t+u/skksuwRVXXIGzzjoLjz76KH7nd34Hl156Ke677z44jrOlvhspJd761rfiBS94Ac4991wAWNbfp4MHD47882Vf2yyM+n4A4LWvfS3OPPNM7N27Fw8++CDe+c534uGHH8ZnPvMZAKv3/WxpESSaXHrppeX9Zz3rWTj//PNx5pln4m//9m8RRdEaXhmx0Xj1q19d3j/vvPPwrGc9C095ylNwzz334IILLljDKzv9XHvttfjOd77TqK8TFYt9P/X68HnnnYc9e/bgggsuwKOPPoqnPOUpq/b7t3Q69GR2EW4lJicn8bSnPQ2PPPIIdu/ejSzLMDs72zhnq35X9jMv9Wdn9+7dCxqsiqLAzMzMlvvOnvzkJ2PHjh145JFHAGyd7+a6667D7bffji9+8Yt4whOeUD6/nL9Pu3fvHvnny762GVjs+xnF+eefDwCNP0Or8f1saRGs7yK02F2E+/btW8MrWx/Mz8/j0UcfxZ49e/Dc5z4Xnuc1vquHH34Y+/fv35Lf1VlnnYXdu3c3vo9ut4v777+//D727duH2dlZPPDAA+U5d999N6SU5V/orcKPf/xjHDt2DHv27AGw+b8bpRSuu+46fPazn8Xdd9+Ns846q/H6cv4+7du3D9/+9rcb/7Fw5513Ynx8HOecc87p+SCniBN9P6P41re+BQCNP0Or8v2cRCPPpuJTn/qUCoJA3Xbbbeq73/2uetOb3qQmJycbHUdbhbe//e3qnnvuUY899pj6p3/6J3XhhReqHTt2qMOHDyullPr1X/919cQnPlHdfffd6hvf+Ibat2+f2rdv3xpf9amj1+upb37zm+qb3/ymAqDe//73q29+85vqhz/8oVJKqT/6oz9Sk5OT6vOf/7x68MEH1eWXX67OOussFcdx+R6XXHKJ+rmf+zl1//33qy9/+cvq7LPPVq95zWvW6iOtGkt9N71eT91www3qvvvuU4899pj6whe+oH7+539enX322SpJkvI9Nut3o5RSb37zm9XExIS655571IEDB8pjMBiU55zo71NRFOrcc89VF110kfrWt76l7rjjDrVz50514403rsVHWlVO9P088sgj6r3vfa/6xje+oR577DH1+c9/Xj35yU9WL37xi8v3WK3vZ8uLoFJK/cVf/IV64hOfqHzfV7/wC7+gvvrVr671Ja0Jr3rVq9SePXuU7/vqZ37mZ9SrXvUq9cgjj5Svx3GsfuM3fkNt27ZNtVot9cpXvlIdOHBgDa/41PLFL35RAVhwXH311UopPSbxu7/7u2rXrl0qCAJ1wQUXqIcffrjxHseOHVOvec1r1NjYmBofH1dveMMbVK/XW4NPs7os9d0MBgN10UUXqZ07dyrP89SZZ56p3vjGNy74D8vN+t0opUZ+NwDUrbfeWp6znL9PP/jBD9Sll16qoihSO3bsUG9/+9tVnuen+dOsPif6fvbv369e/OIXq6mpKRUEgXrqU5+q3vGOd6i5ubnG+6zG90OrlAiCIIgty5auCRIEQRBbGxJBgiAIYstCIkgQBEFsWUgECYIgiC0LiSBBEASxZSERJAiCILYsJIIEQRDEloVEkCAIgtiykAgSxAblnnvuAWNsgQkzQRDLhxxjCGKD8JKXvATPec5z8IEPfACAXgo9MzODXbt2gTG2thdHEBsU2idIEBsU3/c3zUodglgrKB1KEBuA17/+9bj33nvxwQ9+EIwxMMZw2223NdKht912GyYnJ3H77bfj6U9/OlqtFn7lV34Fg8EAH/3oR/GkJz0J27Ztw2/91m9BCFG+d5qmuOGGG/AzP/MzaLfbOP/883HPPfeszQcliNMMRYIEsQH44Ac/iO9973s499xz8d73vhcA8NBDDy04bzAY4EMf+hA+9alPodfr4YorrsArX/lKTE5O4u///u/x7//+77jyyivxghe8AK961asA6MWm3/3ud/GpT30Ke/fuxWc/+1lccskl+Pa3v42zzz77tH5OgjjdkAgSxAZgYmICvu+j1WqVKdB/+7d/W3Benuf4yEc+gqc85SkAgF/5lV/B//gf/wOHDh3C2NgYzjnnHLz0pS/FF7/4RbzqVa/C/v37ceutt2L//v3Yu3cvAOCGG27AHXfcgVtvvRV/+Id/ePo+JEGsASSCBLGJaLVapQACwK5du/CkJz0JY2NjjefsNu5vf/vbEELgaU97WuN90jTF9u3bT89FE8QaQiJIEJsIz/MajxljI5+TUgIA5ufn4TgOHnjgATiO0zivLpwEsVkhESSIDYLv+42GltXg537u5yCEwOHDh/GiF71oVd+bIDYC1B1KEBuEJz3pSbj//vvxgx/8AEePHi2juZ+Gpz3tabjqqqvwute9Dp/5zGfw2GOP4Wtf+xpuuukm/J//839W4aoJYn1DIkgQG4QbbrgBjuPgnHPOwc6dO7F///5Ved9bb731/2/njmkAiGEgCBqJ29AJgpAwzJAKiS9euhkAblfXuM45NTO11qq9d917q7s/uQ9/5mMMALEsQQBiiSAAsUQQgFgiCEAsEQQglggCEEsEAYglggDEEkEAYokgALFEEIBYD7wwBSY+tStoAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "N = 256 # Signal length in time samples.\n", "sb = SignalBank(N=N,Nsub=N//2)\n", "signal_1 = sb.signal_linear_chirp()\n", "\n", "# Let's see the signal spectrogram:\n", "stft = get_stft(signal_1)\n", "spectrogram = np.abs(stft)**2\n", "plt.imshow(spectrogram, origin='lower')\n", "plt.xlabel('time'); plt.ylabel('frequency')\n", "\n", "# Finally, create the dictionary of signals for the benchmark\n", "signals = {'signal_1':signal_1}" ] }, { "cell_type": "markdown", "id": "6e7ce55e", "metadata": {}, "source": [ "## Creating a dictionary of methods to compare" ] }, { "cell_type": "markdown", "id": "177d0d47", "metadata": {}, "source": [ "Before defining the benchmark, let's create a dictionary of methods. Our first signal detection method is based on a matched filter. It will search for a template signal within the signal we probe, and indicate if the correlation between both template and probing signal surpasses a certain threshold. " ] }, { "cell_type": "code", "execution_count": 23, "id": "0d709385", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "from scipy.signal import convolve\n", "def matched_filter(signal, template):\n", " \"\"\"\n", " Applies a matched filter to a signal using a given template.\n", " \"\"\"\n", " \n", " matched_filter_kernel = template[::-1] \n", " # Perform convolution\n", " output = convolve(signal, matched_filter_kernel, mode='same')\n", " return output\n", "\n", "def detection_method_1(signal):\n", " \"\"\" \n", " Signal detection based on matching filter.\n", " \"\"\"\n", " output = matched_filter(signal,template=signal_1)\n", " output /= np.max(output)\n", "\n", " if len(output[output>0.9])==1:\n", " return True\n", " else:\n", " return False\n", "\n", "# Example usage:\n", "signal = np.random.randn(len(signal_1)) + signal_1 # Noisy signal! Should output \"True\" most of the times.\n", "filtered_signal = matched_filter(signal, signal_1)\n", "filtered_signal /= np.max(filtered_signal)\n", "print(detection_method_1(signal))" ] }, { "cell_type": "markdown", "id": "d3cfd320", "metadata": {}, "source": [ "The second signal detection method is a detection test. The null hypothesis is that the probed signal is composed of only white Gaussian noise, whereas the alternative hypothesis is that the probed signal is actually a mixture of signal and white Gaussian noise.\n", "\n", "The test is based on considering that the distribution of each pixel of the spectrogram of white Gaussian noise is distributed as $\\chi^2$ with two degrees of freedom. We then evaluate if any of ten random positions of the spectogram are above a threshold selected to have a false alarm rate of 5%." ] }, { "cell_type": "code", "execution_count": 24, "id": "eefe4c61", "metadata": {}, "outputs": [], "source": [ "import scipy.stats as ss\n", "def detection_method_2(signal):\n", " stft = get_stft(signal,scaling='psd')\n", " std_estim = np.median(np.abs(np.real(stft)))/0.6745\n", " num = ss.chi2.isf(0.05/10,2)\n", " thr = num*std_estim**2\n", " aux = np.abs(stft.flatten())**2\n", " positions = np.random.randint(0,stft.size,size=10)\n", " if np.any( aux[positions] > thr):\n", " return True\n", " else:\n", " return False\n", " \n", "# det = 0\n", "# for i in range(500):\n", "# noise = np.random.randn(32)\n", "# det += detection_method_2(noise)\n", "\n", "# det/500" ] }, { "cell_type": "markdown", "id": "e44fe1b4", "metadata": {}, "source": [ "Finally, we create a dictionary of methods to compare, instantiate a benchmark object and run the comparisons." ] }, { "cell_type": "code", "execution_count": 25, "id": "1b8695ab", "metadata": {}, "outputs": [], "source": [ "methods = {'detection_method_1':detection_method_1,'detection_method_2':detection_method_2}\n", "\n", "benchmark = Benchmark(task='detection',\n", " methods=methods,\n", " # parameters=parameters,\n", " signal_ids=signals,\n", " SNRin=[-10,-5,0,5],\n", " repetitions=30,\n", " N = N)" ] }, { "cell_type": "code", "execution_count": 26, "id": "a242b714", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running benchmark...\n", "- Signal signal_1\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "100%|██████████| 4/4 [00:00<00:00, 14.54it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "The test has finished.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/plain": [ "{'perf_metric': {'signal_1': {-10: {'detection_method_1': {'((), {})': [True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " False,\n", " True,\n", " False,\n", " True,\n", " True,\n", " False,\n", " True,\n", " True,\n", " True]},\n", " 'detection_method_2': {'((), {})': [False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " False]}},\n", " -5: {'detection_method_1': {'((), {})': [True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True]},\n", " 'detection_method_2': {'((), {})': [False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " False,\n", " True,\n", " False,\n", " True,\n", " True,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False,\n", " False]}},\n", " 0: {'detection_method_1': {'((), {})': [True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True]},\n", " 'detection_method_2': {'((), {})': [True,\n", " False,\n", " True,\n", " True,\n", " False,\n", " False,\n", " True,\n", " True,\n", " False,\n", " True,\n", " True,\n", " True,\n", " False,\n", " False,\n", " False,\n", " False,\n", " True,\n", " True,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " True,\n", " False,\n", " False,\n", " True,\n", " True,\n", " True,\n", " False]}},\n", " 5: {'detection_method_1': {'((), {})': [True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True]},\n", " 'detection_method_2': {'((), {})': [True,\n", " False,\n", " False,\n", " True,\n", " True,\n", " True,\n", " True,\n", " False,\n", " False,\n", " True,\n", " True,\n", " False,\n", " True,\n", " True,\n", " False,\n", " True,\n", " False,\n", " False,\n", " True,\n", " False,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " True,\n", " False,\n", " False,\n", " False]}}}}}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "benchmark.run()" ] }, { "cell_type": "markdown", "id": "a8c7ff25", "metadata": {}, "source": [ "## Showcasing results" ] }, { "cell_type": "markdown", "id": "6c53de7c", "metadata": {}, "source": [ "Once results are available we can display summary plots using the functionality of the `ResultsInterpreter` class." ] }, { "cell_type": "code", "execution_count": 27, "id": "0db8cf79", "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "linkText": "Export to plot.ly", "plotlyServerURL": "https://plot.ly", "showLink": false }, "data": [ { "alignmentgroup": "True", "error_x": { "array": [ "-10", "-5", "0", "5" ] }, "error_y": { "array": [ 0.08377753664806065, 0, 0, 0 ], "arrayminus": [ 0.1900103086597359, 0.13590067257572858, 0.13590067257572858, 0.13590067257572858 ] }, "hovertemplate": "Method + Param=detection_method_1
SNRin=%{x}
QRF=%{y}", "legendgroup": "detection_method_1", "marker": { "color": "#636efa", "pattern": { "shape": "" } }, "name": "detection_method_1", "offsetgroup": "detection_method_1", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "-10", "-5", "0", "5" ], "xaxis": "x", "y": [ 0.9, 1, 1, 1 ], "yaxis": "y" }, { "alignmentgroup": "True", "error_x": { "array": [ "-10", "-5", "0", "5" ] }, "error_y": { "array": [ 0.19001030865973592, 0.21162368367446655, 0.20946665887844174, 0.19299006128722296 ], "arrayminus": [ 0.08377753664806069, 0.13389194280703817, 0.20946665887844157, 0.21848056550271083 ] }, "hovertemplate": "Method + Param=detection_method_2
SNRin=%{x}
QRF=%{y}", "legendgroup": "detection_method_2", "marker": { "color": "#EF553B", "pattern": { "shape": "" } }, "name": "detection_method_2", "offsetgroup": "detection_method_2", "orientation": "v", "showlegend": true, "textposition": "auto", "type": "bar", "x": [ "-10", "-5", "0", "5" ], "xaxis": "x", "y": [ 0.1, 0.2, 0.5, 0.6 ], "yaxis": "y" } ], "layout": { "barmode": "group", "legend": { "title": { "text": "Method + Param" }, "tracegroupgap": 0 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "signal_1" }, "xaxis": { "anchor": "y", "domain": [ 0, 1 ], "title": { "text": "SNRin (dB)" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "Prob. of Detection" } } } }, "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Summary interactive plots with Plotly and a report.\n", "from plotly.offline import iplot\n", "import plotly.io as pio\n", "pio.renderers.default = \"plotly_mimetype+notebook\"\n", "interpreter = ResultsInterpreter(benchmark)\n", "figs = interpreter.get_summary_plotlys(bars=True,ylabel='Prob. of Detection')\n", "for fig in figs:\n", " iplot(fig)" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.2" } }, "nbformat": 4, "nbformat_minor": 5 }