{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# TriScale Interactive Plots\n", "\n", "This notebook generates and displays all the plots from the _TriScale_ paper.\n", "By default, large versions of the plots are shown. To exactly reproduce the plots from the paper, set `PaperPlots=True` in the first cell.\n", "\n", "- [Figure 1](#Figure-1)\n", " - [Figure 1.a](#Figure-1a)\n", " - [Figure 1.b](#Figure-1b)\n", "- [Figure 3](#Figure-3)\n", " - [Figure 3.a](#Figure-3a)\n", " - [Figure 3.b](#Figure-3b)\n", " - [Figure 3.c](#Figure-3c)\n", "- [Figure 4](#Figure-4)\n", "- [Figure 5](#Figure-5)\n", "- [Figure 7](#Figure-7)\n", "- [Figure 8](#Figure-8)\n", "- [Figure 9](#Figure-9)\n", "- [Figure 10](#Figure-10)\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Set to False to view larger versions of the plots\n", "# Set to True to reproduce the exact plots from the paper\n", "PaperPlot = False" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import copy\n", "import json\n", "import os\n", "from pathlib import Path\n", "import yaml\n", "import zipfile\n", "\n", "import numpy as np\n", "import pandas as pd\n", "import plotly.graph_objects as go\n", "import plotly.io as pio\n", "pio.renderers.default = \"notebook\"\n", "\n", "import triscale\n", "import triplots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Download Source Files and Data\n", "[[Back to top](#TriScale)]\n", "\n", "The entire dataset for this case study is available on Zenodo: \n", "\n", "[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3451417.svg)](https://doi.org/10.5281/zenodo.3451417)\n", "\n", "The wget commands below download the required files to reproduce this case study.\n", "> **The .zip file is ~2.7 GB**" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nothing to download\n" ] } ], "source": [ "# Set `download = True` to download (and extract) the data from this case study\n", "# Eventually, adjust the record_id for the file version you are interested in.\n", "\n", "# For reproducing the original TriScale paper, set `record_id = 3666724`\n", "\n", "download = False\n", "record_id = 3666724 # v3.0.1 (https://doi.org/10.5281/zenodo.3666724)\n", "\n", "files= ['UseCase_Pantheon.zip',\n", " 'UseCase_Glossy.zip'\n", " 'UseCase_VideoStreaming.zip'\n", " 'UseCase_FailureDetection.zip']\n", "if download:\n", " for file in files:\n", " print(file)\n", " url = 'https://zenodo.org/record/'+str(record_id)+'/files/'+file \n", " os.system('wget %s' %url)\n", " if file[-4:] == '.zip': \n", " with zipfile.ZipFile(file,\"r\") as zip_file:\n", " zip_file.extractall()\n", " print('Done.')\n", "else: \n", " print('Nothing to download')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import UseCase_Pantheon.pantheon as pantheon\n", "import UseCase_Glossy.flocklab as flocklab\n", "import UseCase_VideoStreaming.videostreaming as vs\n", "import UseCase_FailureDetection.failuredetection as fd" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Select the different output format settings\n", "\n", "if PaperPlot:\n", " output_format = 'CCR'\n", "else:\n", " output_format = 'online'\n", "\n", "if output_format == 'online':\n", " font_size_px = 14\n", " linewidth_px = 512\n", " landscapewidth_px = 654\n", " plot_path = None\n", " \n", " plot_path = Path('plots')\n", "\n", "if output_format == 'CCR':\n", " font_size_pt = 7\n", " offset = 5 # to compensate for the rounding of unit conversions\n", " linewidth_pt = 241 - offset \n", " landscapewidth_pt = 506 - offset\n", " \n", " # 1pt = 1.333px\n", " font_size_px = int(font_size_pt*1.333)+1\n", " linewidth_px = int(linewidth_pt*1.333)+1\n", " landscapewidth_px = int(landscapewidth_pt*1.333)+1\n", "\n", " plot_path = Path('plots_ccr')\n", " \n", "# Create plot directory if don't exist\n", "if (plot_path is not None) and not (os.path.exists(plot_path)):\n", " os.mkdir(plot_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 1a" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Set to False to see the full range of the axes\n", "# Set to True to reproduce the figure shown in the paper\n", "zoom = True\n", "\n", "data_path = Path('UseCase_Pantheon/PantheonData/10runs_30s/2019-08-20T15:34:33:+0200')\n", "perf_file = data_path / 'pantheon_perf.json'\n", "meta_file = data_path / 'pantheon_metadata.json'\n", "config_file = Path('UseCase_Pantheon/PantheonData/config.yml')\n", "\n", "custom_layout = {\n", " \"title\":None,\n", " \"showlegend\":False,\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'range':[100,32],\n", " 'autorange':False,\n", " 'title':{'font':{'size':font_size_px}}},\n", " \"yaxis\":{'range':[-7,127],\n", " 'title':{'font':{'size':font_size_px}}},\n", "}\n", "\n", "# Adjust the axis ranges and file name\n", "if zoom:\n", " custom_layout[\"yaxis\"][\"range\"]=[80,122]\n", " custom_layout[\"xaxis\"][\"range\"]=[100,38]\n", " plot_filename = \"plot_zoom_pantheon.pdf\"\n", "else: \n", " plot_filename = \"plot_summary_pantheon.pdf\"\n", "\n", "if PaperPlot:\n", " plot_filename = str(plot_path/plot_filename)\n", "else:\n", " plot_filename = None\n", " \n", " \n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 0.8*landscapewidth_px\n", " custom_layout['height'] = 500\n", " custom_layout['margin'] = dict(l=65, r=0, t=70, b=65)\n", "\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = 0.4*landscapewidth_px\n", " custom_layout['height'] = 185\n", " custom_layout['margin'] = dict(l=30, r=0, t=25, b=40)\n", "\n", "# Produce the plot\n", "pantheon.plot_pantheon(perf_file, \n", " meta_file, \n", " config_file, \n", " layout=custom_layout,\n", " out_name=plot_filename,\n", " show=True);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 1b" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Set to False to see the full range of the axes\n", "# Set to True to reproduce the figure shown in the paper\n", "zoom = True\n", "\n", "result_dir_path = Path('UseCase_Pantheon/PantheonData/10runs_30s')\n", "result_dir_list = [x for x in result_dir_path.iterdir() if x.is_dir()]\n", "meta_data_file = 'pantheon_metadata.json'\n", "config_file = Path('UseCase_Pantheon/PantheonData/config.yml')\n", "out_name = Path('UseCase_Pantheon/PantheonData/metrics_wo_convergence.csv')\n", "\n", "# Definition of metrics and KPIs for TriScale analysis\n", "convergence = {'expected': True,\n", " 'confidence': 95, # in %\n", " 'tolerance': 5, # in %\n", " }\n", "metric_tput = {'name':'Mean throughput',\n", " 'unit': 'Mbit/s',\n", " 'measure':'mean',\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "metric_delay = {'name':'95th perc. of one-way delay',\n", " 'unit': 'ms',\n", " 'measure':95,\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "KPI_tput = {'percentile': 25,\n", " 'confidence': 75,\n", " 'name': 'KPI of throughput metric',\n", " 'unit': 'Mbit/s',\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "KPI_delay = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': 'KPI of one-way delay metric',\n", " 'unit': 'ms',\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "\n", "metric_list = [metric_tput, metric_delay]\n", "kpi_list = [ KPI_tput, KPI_delay ]\n", "metrics, figure = pantheon.compute_metric(result_dir_list, \n", " meta_data_file, \n", " convergence,\n", " metric_list,\n", " out_name=out_name,\n", " plot=False,\n", " verbose=False)\n", "\n", "custom_layout = {\n", " \"title\":None,\n", " \"showlegend\":False,\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'range':[100,32],\n", " 'autorange':False,\n", " 'title':{'font':{'size':font_size_px}}},\n", " \"yaxis\":{'range':[-7,127]},\n", "}\n", "\n", "# Adjust the Y-axis range and file name\n", "if zoom:\n", " custom_layout[\"xaxis\"][\"range\"]=[100,38]\n", " custom_layout[\"yaxis\"][\"range\"]=[78,122]\n", " plot_filename = \"plot_zoom_triscale_wo_convergence.pdf\"\n", "else: \n", " plot_filename = \"plot_summary_triscale.pdf\"\n", "\n", "if PaperPlot:\n", " plot_filename = str(plot_path/plot_filename)\n", "else:\n", " plot_filename = None\n", " \n", " \n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 0.8*landscapewidth_px\n", " custom_layout['height'] = 500\n", " custom_layout['margin'] = dict(l=65, r=0, t=70, b=65)\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = 0.4*landscapewidth_px\n", " custom_layout['height'] = 185\n", " custom_layout['margin'] = dict(l=30, r=0, t=25, b=40)\n", "\n", " \n", "series_label = np.sort(metrics['datetime'].unique())\n", "for series_ix in [series_label[0]]:\n", "\n", " # Get the metrics values for one series\n", " metric_series = metrics.loc[metrics['datetime'] == series_ix]\n", "\n", " # Plot them\n", " pantheon.plot_triscale_kpi(metric_series, \n", " result_dir_list[0] / meta_data_file, \n", " kpi_list,\n", " config_file,\n", " layout=custom_layout, \n", " out_name=plot_filename,\n", " show=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 3a" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Construct the path to the different test results\n", "result_dir_path = Path('UseCase_Pantheon/PantheonData/10runs_30s')\n", "result_dir_list = [x for x in result_dir_path.iterdir() if x.is_dir()]\n", "# Meta data file name\n", "meta_data_file = 'pantheon_metadata.json'\n", "# Config file name and path\n", "config_file = Path('UseCase_Pantheon/PantheonData/config.yml')\n", "out_name = Path('UseCase_Pantheon/PantheonData/metrics.csv')\n", "\n", "# Inputs\n", "metric_delay = {'name':'One-way delay',\n", " 'unit': 'ms',\n", " 'measure':95,\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "convergence = {'expected': True,\n", " 'confidence': 95, # in %\n", " 'tolerance': 5, # in %\n", " }\n", "\n", "# load the metrics\n", "metrics = pantheon.compute_metric(result_dir_list, \n", " meta_data_file, \n", " convergence,\n", " [metric_delay],\n", " out_name = out_name)\n", "\n", "data_file = str(result_dir_list[0] / 'cubic_datalink_delay_run1_flow1.csv')\n", "\n", "# Plot file name\n", "plot_out_name = \"plot_example_metric.pdf\"\n", "if PaperPlot:\n", " plot_out_name = str(plot_path/plot_out_name)\n", "else:\n", " plot_out_name = None\n", "\n", "# Horizontal Y-axis title\n", "ytitle = {\n", " \"x\":0,\n", " \"y\":1.10,\n", " \"xref\":\"paper\",\n", " \"yref\":\"paper\",\n", " \"text\":metric_delay['name'] +' [ '+ metric_delay['unit'] +' ]',\n", " \"showarrow\":False,\n", " \"xanchor\":'left'\n", "}\n", "\n", "custom_layout = {\n", " \"title\":None,\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px},\n", " 'text':'Time [ s ]'}\n", " },\n", " \"yaxis\":{'title':{'text':''}},\n", " \"annotations\":[ytitle] \n", "}\n", "\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 1.2*landscapewidth_px\n", " custom_layout['height'] = 400\n", " custom_layout['margin'] = dict(l=65, r=0, t=70, b=65)\n", "# custom_layout[\"legend\"] = dict(x=0.1, y=0.1)\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = 0.60*landscapewidth_px\n", " custom_layout['height'] = 200\n", " custom_layout['margin'] = dict(l=20, r=0, t=30, b=25)\n", " custom_layout['showlegend'] = False\n", " custom_layout[\"legend\"] = dict(xanchor='center',\n", " x=0.5,\n", " yanchor='bottom',\n", " y=0.1, \n", " font=dict(size=font_size_px-2),\n", " orientation='h')\n", " \n", "# Produce the plot\n", "triscale.analysis_metric( data_file,\n", " metric_delay,\n", " plot=True,\n", " plot_out_name=plot_out_name,\n", " custom_layout = custom_layout,\n", " convergence=convergence);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 3b" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Construct the path to the different test results\n", "result_dir_path = Path('UseCase_Pantheon/PantheonData/10runs_30s')\n", "result_dir_list = [x for x in result_dir_path.iterdir() if x.is_dir()]\n", "# Meta data file name\n", "meta_data_file = 'pantheon_metadata.json'\n", "# Config file name and path\n", "config_file = Path('UseCase_Pantheon/PantheonData/config.yml')\n", "out_name = Path('UseCase_Pantheon/PantheonData/metrics.csv')\n", "\n", "# Inputs\n", "metric_delay = {'name':'One-way delay',\n", " 'unit': 'ms',\n", " 'measure':95,\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "convergence = {'expected': True,\n", " 'confidence': 95, # in %\n", " 'tolerance': 5, # in %\n", " }\n", "KPI_delay = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': 'One-way delay',\n", " 'unit': 'ms',\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "\n", "# Compute/load the metrics\n", "metrics, figure = pantheon.compute_metric(result_dir_list, \n", " meta_data_file, \n", " convergence,\n", " [metric_delay],\n", " out_name = out_name\n", " )\n", "\n", "# File name for saving plot\n", "plot_out_name = \"plot_example_KPI.pdf\"\n", "if PaperPlot:\n", " plot_out_name = str(plot_path/plot_out_name)\n", "else:\n", " plot_out_name = None\n", " \n", "metric_data = np.array(metrics.loc[(metrics['cc'] == 'cubic') &\n", " (metrics['datetime'] == result_dir_list[1].stem)].delay_value)\n", "\n", "# Compute the KPI\n", "out = triscale.analysis_kpi(metric_data,\n", " KPI_delay);\n", "# KPI annotation\n", "note = go.layout.Annotation(\n", " x=0.5,\n", " y=1,\n", " xref=\"paper\",\n", " yref=\"paper\",\n", " yanchor=\"bottom\",\n", " text=\"KPI: %2.2f ms\" % out[1],\n", " showarrow=False,\n", " font={'size':font_size_px+2 }\n", " )\n", "\n", "custom_layout = {\n", " \"title\":None,\n", " \"width\":0.5*linewidth_px,\n", " \"height\":100,\n", " \"margin\":dict(l=0, r=0, t=5, b=40),\n", " \"font\":{\"size\":font_size_px},\n", " \"showlegend\": False,\n", " \"yaxis\":{'title':{'font':{'size':font_size_px}}},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px},\n", " 'text':'One-way delay metric [ms]'}},\n", " \"annotations\":[note]\n", "}\n", "\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 0.5*linewidth_px\n", " custom_layout['height'] = 100\n", " custom_layout['margin'] = dict(l=0, r=0, t=5, b=40)\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = 0.22*landscapewidth_px\n", " custom_layout['height'] = 60\n", " custom_layout['margin'] = dict(l=0, r=10, t=15, b=25)\n", " \n", "# Produce the plot\n", "out = triscale.analysis_kpi(metric_data,\n", " KPI_delay,\n", " to_plot=['horizontal'],\n", " plot_out_name=plot_out_name,\n", " custom_layout=custom_layout);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 3c" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Invalid metric data (only one data point)\n", "Invalid metric data (only one data point)\n", "Invalid metric data (only one data point)\n", "Invalid metric data (only one data point)\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "KPI_tput = {'percentile': 25,\n", " 'confidence': 75,\n", " 'name': 'Average Throughput',\n", " 'unit': 'Mbit/s',\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "KPI_delay = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': 'One-way delay',\n", " 'unit': 'ms',\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "score_delay = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': '95th perc. of One-way delay',\n", " 'unit': 'ms',\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "# Compute the KPIs\n", "kpis = pantheon.compute_kpi(metrics,\n", " [KPI_tput, KPI_delay],\n", " 'datetime',\n", " plot=False,\n", " verbose=False)\n", "\n", "plot_out_name = \"plot_example_var_score.pdf\"\n", "if PaperPlot:\n", " plot_out_name = str(plot_path/plot_out_name)\n", "else:\n", " plot_out_name = None\n", "\n", "kpi_data = np.array(kpis.loc[(kpis['cc'] == 'cubic')].delay_value)\n", "\n", "# Compute the variability score\n", "out = triscale.analysis_variability(kpi_data,\n", " score_delay);\n", "\n", "note = go.layout.Annotation(\n", " x=0.5,\n", " y=1,\n", " xref=\"paper\",\n", " yref=\"paper\",\n", " yanchor=\"bottom\",\n", " text=\"Var. Score: %2.2f ms\" % out[3],\n", " showarrow=False,\n", " font={'size':font_size_px+2 }\n", " )\n", "custom_layout = {\n", " \"title\":None,\n", " \"showlegend\": False,\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px},\n", " 'text':'One-way delay KPI [ms]'}\n", " },\n", " \"annotations\":[note]\n", "\n", "}\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 0.5*linewidth_px\n", " custom_layout['height'] = 100\n", " custom_layout['margin'] = dict(l=0, r=0, t=5, b=40)\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = 0.22*landscapewidth_px\n", " custom_layout['height'] = 60\n", " custom_layout['margin'] = dict(l=0, r=10, t=15, b=25)\n", " \n", "# Produce the plot\n", "triscale.analysis_variability(kpi_data,\n", " score_delay,\n", " to_plot=['horizontal'],\n", " plot_out_name=plot_out_name,\n", " custom_layout=custom_layout);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 4" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# TriScale metric definition\n", "metric_tput = {'name':'Median throughput',\n", " 'unit': 'Mbit/s',\n", " 'measure':50,\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "convergence = {'expected': True,\n", " 'confidence': 95, # in %\n", " 'tolerance': 5, # in %\n", " }\n", "\n", "# Selection of the data to plot\n", "result_dir_path = Path('UseCase_Pantheon/PantheonData/10_20_30_40_50_60s')\n", "result_dir_list = [x for x in result_dir_path.iterdir() if x.is_dir()]\n", "result_dir_list = sorted(result_dir_list)\n", "meta_data_file = 'pantheon_metadata.json'\n", "sample = {'cc':'ledbat',\n", " 'run':1}\n", "\n", "# Horizontal Y axis label\n", "ytitle = {\n", " \"x\":0,\n", " \"y\":1.15,\n", " \"xref\":\"paper\",\n", " \"yref\":\"paper\",\n", " \"text\":'Throughput [ '+ metric_tput['unit'] +' ]',\n", " \"showarrow\":False,\n", " \"xanchor\":'left'\n", "}\n", "\n", "# General layout\n", "custom_layout = {\n", " 'title':None,\n", " \"font\":{\"size\":font_size_px},\n", " \"legend\":{'x':.1, 'y':.9,'font':{'size':font_size_px-2}},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px},\n", " 'text':'Time [ s ]',},\n", " 'zeroline':False\n", " },\n", " \"yaxis\":{'title':{'text':''}}, \n", " \"annotations\":[ytitle]\n", "}\n", "\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 0.6*linewidth_px\n", " custom_layout['height'] = 220\n", " custom_layout['margin'] = dict(l=40, r=0, t=35, b=40)\n", " custom_layout[\"legend\"] = dict()\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = 0.27*landscapewidth_px\n", " custom_layout['height'] = 125\n", " custom_layout['margin'] = dict(l=25, r=0, t=25, b=30)\n", " custom_layout[\"yaxis\"][\"range\"]=[0,110]\n", " custom_layout[\"legend\"] = dict(xanchor='right',\n", " x=1, \n", " y=1, \n", " font=dict(size=font_size_px-2))\n", " custom_layout['showlegend'] = False\n", "\n", "# ordered of tests is all messed-up...\n", "runtimes = [30,10,20,60,40,50]\n", "\n", "# Do only the 30s and 60s plots\n", "## 30s\n", "i = 0\n", "plot_out_name = \"plot_ledbat_%s_runtime.pdf\" % runtimes[i]\n", "metrics_design, figure = pantheon.compute_metric( [result_dir_list[i]], \n", " meta_data_file, \n", " convergence,\n", " [metric_tput],\n", " plot=True,\n", " showplot=False,\n", " layout=custom_layout,\n", " verbose=False,\n", " sample=sample)\n", "\n", "# Adjust the figure and save\n", "figure.update_traces(marker=dict(size=font_size_px/4))\n", "figure.write_image(str(plot_path/plot_out_name))\n", "figure.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " figure.write_image(str(plot_path/plot_out_name))\n", "\n", "## 60s\n", "i = 3\n", "custom_layout['width'] = custom_layout['width']*1.68 # make the x axis (roughly) the same scale\n", "plot_out_name = \"plot_ledbat_%s_runtime.pdf\" % runtimes[i]\n", "metrics_design, figure = pantheon.compute_metric( [result_dir_list[i]], \n", " meta_data_file, \n", " convergence,\n", " [metric_tput],\n", " plot=True,\n", " showplot=False,\n", " layout=custom_layout,\n", " verbose=False,\n", " sample=sample)\n", "\n", "# Adjust the figure and save\n", "figure.update_traces(marker=dict(size=font_size_px/4))\n", "figure.write_image(str(plot_path/plot_out_name))\n", "figure.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " figure.write_image(str(plot_path/plot_out_name))\n", " \n", "if PaperPlot:\n", " # Create a figure with only the legend visible\n", " custom_layout['showlegend'] = True\n", " custom_layout['width'] = 0.133*landscapewidth_px\n", " custom_layout['height'] = 100\n", " custom_layout['margin'] = dict(l=0, r=0, t=0, b=0)\n", " custom_layout['xaxis'] = dict(visible=False, showline=False)\n", " custom_layout['yaxis'] = dict(visible=False, showline=False)\n", " custom_layout['annotations'][0]['visible']=False\n", "\n", " figure.update_layout(custom_layout)\n", " figure.show()\n", " figure.write_image(str(plot_path/'plot_ledbat_legend.pdf'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 5" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "data_file = Path('UseCase_Glossy/Data_FlockLab/2019-08_FlockLab_sky.csv')\n", "df = flocklab.parse_data_file(str(data_file), active_link_threshold=50)\n", "plot_name = 'plot_flocklab_autocorr.pdf'\n", "\n", "link_quality_bounds = [0,100]\n", "link_quality_name = 'PRR [%]'\n", "\n", "# Produce the plot\n", "fig_theil, fig_autocorr = triscale.network_profiling(df, link_quality_bounds, link_quality_name)\n", "\n", "# Adjust layout\n", "custom_layout = {\n", " 'title':None,\n", " \"font\":{\"size\":font_size_px},\n", " \"legend\":{'x':.4, 'y':0.9,'font':{'size':font_size_px}},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px},\n", " 'text':'Lag'}\n", " },\n", "}\n", "\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 1.5*linewidth_px\n", " custom_layout['height'] = 400\n", " custom_layout['margin'] = dict(l=40, r=0, t=0, b=35)\n", " custom_layout[\"legend\"] = dict(xanchor='right',\n", " x=1, \n", " y=1, \n", " font=dict(size=font_size_px))\n", " # convert the displayed values from lag to days\n", " fig_autocorr.update_xaxes(\n", " tickvals=[12,84,168,252],\n", " ticktext=[1,7,14,21])\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = linewidth_px\n", " custom_layout['height'] = 180\n", " custom_layout['margin'] = dict(l=20, r=0, t=0, b=35)\n", " custom_layout[\"legend\"] = dict(xanchor='right',\n", " x=1, \n", " y=1, \n", " font=dict(size=font_size_px))\n", " # convert the displayed values from lag to days\n", " fig_autocorr.update_xaxes(\n", " tickvals=[12,84,168,252],\n", " ticktext=[1,7,14,21])\n", "\n", "# Show plot\n", "fig_autocorr.update_layout(custom_layout)\n", "fig_autocorr.update_xaxes(title_text='Lag (days)')\n", "fig_autocorr.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " fig_autocorr.write_image(str(plot_path/plot_name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 7" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Path to test results\n", "result_dir_path = Path('UseCase_VideoStreaming/FCC/linear')\n", "\n", "# Metadata\n", "protocol_list = [x.stem for x in result_dir_path.iterdir()]\n", "protocol_list = list(set(protocol_list)) # make list elements unique\n", "config_file = Path('UseCase_VideoStreaming/config.yml')\n", "\n", "# Define the KPIs\n", "KPI_percentiles = np.arange(2,100,2) # percentiles\n", "KPI_confidence = 95 # confidence level\n", "KPI_base = {'confidence': KPI_confidence,\n", " 'bound': 'lower',\n", " 'bounds': [-3,3],\n", " 'unit': '',\n", " }\n", "KPI_list = []\n", "for p in KPI_percentiles:\n", " kpi = copy.deepcopy(KPI_base)\n", " kpi['percentile'] = p\n", " kpi['name'] = 'P%d'%p\n", " KPI_list.append(kpi)\n", " \n", "# Compute/load KPIs values\n", "out_name = Path('UseCase_VideoStreaming') / 'kpis.csv'\n", "QoE = vs.compute_kpi(\n", " protocol_list,\n", " KPI_list,\n", " result_dir_path,\n", " out_name=out_name\n", ")\n", "\n", "plot_out_name = \"plot_vs_pensieve.pdf\"\n", "sample = dict(\n", " sample_cdf=True,\n", " protocol=['pensieve']\n", ")\n", "figure = vs.plot_cdf(\n", " QoE,\n", " config_file,\n", " result_dir_path,\n", " sample=sample\n", ")\n", "\n", "# Set layout\n", "custom_layout = {\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px}},\n", " 'rangemode':'nonnegative'},\n", " \"yaxis\":{'title':{'font':{'size':font_size_px}}},\n", " \"legend\": dict(x=0.97, \n", " y=0.1, \n", " orientation='v',\n", " xanchor='right',\n", " font=dict(size=font_size_px))\n", "}\n", "\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = 1.5*linewidth_px\n", " custom_layout['height'] = 300\n", " custom_layout['margin'] = dict(l=40, r=0, t=35, b=40)\n", " custom_layout[\"legend\"] = dict()\n", "if output_format == 'CCR':\n", " custom_layout[\"width\"] = 0.8*linewidth_px\n", " custom_layout[\"height\"] = 120\n", " custom_layout[\"margin\"] = dict(l=35, r=0, t=0, b=25)\n", " \n", "figure.update_layout(custom_layout)\n", "figure.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " figure.write_image(str(plot_path/plot_out_name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 8" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "result_dir_path = Path('UseCase_Pantheon/PantheonData/10runs_30s')\n", "result_dir_list = [x for x in result_dir_path.iterdir() if x.is_dir()]\n", "meta_data_file = 'pantheon_metadata.json'\n", "config_file = Path('UseCase_Pantheon/PantheonData/config.yml')\n", "convergence = {'expected': False,\n", " 'confidence': 95, # in %\n", " 'tolerance': 5, # in %\n", " }\n", "metric_tput = {'name':'Median throughput',\n", " 'unit': 'MBit/s',\n", " 'measure':'mean',\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "metric_delay = {'name':'95th perc. of one-way delay',\n", " 'unit': 'ms',\n", " 'measure':95,\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "KPI_tput = {'percentile': 25,\n", " 'confidence': 75,\n", " 'name': 'KPI throughput',\n", " 'unit': 'MBit/s',\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "KPI_delay = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': 'KPI One-way delay',\n", " 'unit': 'ms',\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "score_tput = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': 'Throughput',\n", " 'unit': 'MBit/s',\n", " 'bounds':[0,120], # expected value range\n", " 'tag':'throughput' # do not change the tag\n", " }\n", "score_delay = {'percentile': 75,\n", " 'confidence': 75,\n", " 'name': 'One-way delay',\n", " 'unit': 'ms',\n", " 'bounds':[0,100], # expected value range\n", " 'tag':'delay' # do not change the tag\n", " }\n", "\n", "out_name = Path('UseCase_Pantheon/PantheonData/metrics_wo_convergence.csv')\n", "\n", "metric_list = [metric_tput, metric_delay]\n", "kpi_list = [ KPI_tput, KPI_delay ]\n", "score_list = [ score_tput, score_delay ]\n", "\n", "metrics, figure = pantheon.compute_metric(result_dir_list, \n", " meta_data_file, \n", " convergence,\n", " metric_list,\n", " out_name=out_name,\n", " force_computation=False,\n", " plot=False,\n", " verbose=False)\n", "KPIs = pantheon.compute_kpi(metrics,\n", " kpi_list,\n", " series='datetime',\n", " plot=False,\n", " verbose=False)\n", "scores = pantheon.compute_score(KPIs,\n", " score_list,\n", " plot=False,\n", " verbose=False)\n", "custom_layout = {\n", " 'title':None,\n", " 'font':{\"size\":font_size_px},\n", " 'xaxis':{'tickangle':-45,\n", " 'title':{'font':{'size':font_size_px-2}}},\n", " 'xaxis2':{'tickangle':-45,\n", " 'title':{'font':{'size':font_size_px-2}}}\n", "}\n", "\n", "# Adjust the plot size \n", "if output_format == 'online':\n", " custom_layout['width'] = linewidth_px\n", " custom_layout['height'] = 650\n", " custom_layout['margin'] = dict()\n", " \n", " # Plot two graphs in column\n", " in_column = True\n", "\n", "if output_format == 'CCR':\n", " custom_layout['width'] = linewidth_px\n", " custom_layout['height'] = 350\n", " custom_layout['margin'] = dict(l=40, r=10, t=0, b=55)\n", " \n", " # Plot two graphs in column\n", " in_column = True\n", " \n", "\n", "# Produce the figure\n", "plot_out_name = \"plot_score_matrix.pdf\"\n", "figure = pantheon.plot_triscale_scores_matrix( scores,\n", " score_list,\n", " config_file,\n", " layout = custom_layout,\n", " in_column=in_column,\n", " show=False\n", " )\n", "# Adjust the column title font size\n", "for i in figure['layout']['annotations']:\n", " i['font'] = dict(size=font_size_px)\n", "\n", "# Save and show\n", "figure.write_image(str(plot_path/plot_out_name))\n", "figure.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 9" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# === TPR ===\n", "\n", "plot_out_name = \"plot_fd_tpr.pdf\"\n", "\n", "# Construct the path to the different test results\n", "result_dir = Path('UseCase_FailureDetection')\n", "config_file = Path('UseCase_FailureDetection/config.yml')\n", "out_file = result_dir / 'kpis.csv'\n", "\n", "# KPI definition\n", "KPI = { 'percentile' : 50,\n", " 'confidence' : 95,\n", " 'bounds': [0,1],\n", " 'bound': 'lower'\n", " }\n", "\n", "# Retrieve KPIs\n", "metric_df = None\n", "kpis = fd.compute_kpis(metric_df,KPI,config_file,out_name=out_file)\n", "\n", "# Generate the figure\n", "figure = fd.plot_TPR(kpis,config_file)\n", "\n", "# Set layout\n", "custom_layout = {\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px}}},\n", " \"yaxis\":{'title':{'font':{'size':font_size_px}}},\n", " \"legend\": dict(x=0.5, \n", " y=0.1, \n", " orientation='h',\n", " xanchor='center',\n", " font=dict(size=font_size_px-2))\n", "}\n", "if output_format == 'online':\n", " custom_layout['width'] = 1.5*linewidth_px\n", " custom_layout['height'] = 300\n", " custom_layout['margin'] = dict(l=40, r=0, t=35, b=40)\n", " custom_layout[\"legend\"] = dict()\n", " \n", "if output_format == 'CCR':\n", " custom_layout[\"width\"] = linewidth_px\n", " custom_layout[\"height\"] = 125\n", " custom_layout[\"margin\"] = dict(l=35, r=0, t=0, b=30)\n", " custom_layout[\"legend\"]['yanchor'] = 'bottom'\n", " custom_layout[\"legend\"]['y'] = 0.97\n", "\n", "figure.update_layout(custom_layout)\n", "figure.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " figure.write_image(str(plot_path/plot_out_name))\n", "\n", " \n", "# === Speed ===\n", " \n", "plot_out_name = \"plot_fd_speed.pdf\"\n", "\n", "# Generate the figure\n", "figure = fd.plot_speed(kpis,config_file)\n", "\n", "# Ajust layout\n", "if output_format == 'online':\n", " custom_layout['width'] = 1.5*linewidth_px\n", " custom_layout['height'] = 300\n", " custom_layout['margin'] = dict(l=40, r=0, t=35, b=40)\n", " custom_layout[\"legend\"] = dict()\n", "if output_format == 'CCR':\n", " custom_layout['showlegend'] = False\n", " custom_layout[\"height\"]-= 20\n", " \n", "figure.update_layout(custom_layout)\n", "figure.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " figure.write_image(str(plot_path/plot_out_name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Figure 10" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output retrieved from file. Skipping computation.\n" ] }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Path to test results\n", "result_dir_path = Path('UseCase_VideoStreaming/FCC/linear')\n", "\n", "# Metadata\n", "protocol_list = [x.stem for x in result_dir_path.iterdir()]\n", "protocol_list = list(set(protocol_list)) # make list elements unique\n", "config_file = Path('UseCase_VideoStreaming/config.yml')\n", "\n", "# Define the KPIs\n", "KPI_percentiles = np.arange(2,100,2) # percentiles\n", "KPI_confidence = 95 # confidence level\n", "KPI_base = {'confidence': KPI_confidence,\n", " 'bound': 'lower',\n", " 'bounds': [-3,3],\n", " 'unit': '',\n", " }\n", "KPI_list = []\n", "for p in KPI_percentiles:\n", " kpi = copy.deepcopy(KPI_base)\n", " kpi['percentile'] = p\n", " kpi['name'] = 'P%d'%p\n", " KPI_list.append(kpi)\n", " \n", "# Compute/load KPIs values\n", "out_name = Path('UseCase_VideoStreaming') / 'kpis.csv'\n", "QoE = vs.compute_kpi(\n", " protocol_list,\n", " KPI_list,\n", " result_dir_path,\n", " out_name=out_name\n", ")\n", "\n", "plot_out_name = \"plot_vs_all.pdf\"\n", "sample = dict(\n", " sample_cdf=False,\n", ")\n", "figure = vs.plot_cdf(\n", " QoE,\n", " config_file,\n", " result_dir_path,\n", " sample=sample\n", ")\n", "\n", "# Set layout\n", "custom_layout = {\n", " \"font\":{\"size\":font_size_px},\n", " \"xaxis\":{'title':{'font':{'size':font_size_px}},\n", " 'rangemode':'nonnegative'},\n", " \"yaxis\":{'title':{'font':{'size':font_size_px}}},\n", " \"legend\": dict(x=0.97, \n", " y=0.1, \n", " orientation='v',\n", " xanchor='right',\n", " font=dict(size=font_size_px))\n", "}\n", "\n", "\n", "# Ajust layout\n", "if output_format == 'online':\n", " custom_layout['width'] = 1.5*linewidth_px\n", " custom_layout['height'] = 300\n", " custom_layout['margin'] = dict(l=40, r=0, t=35, b=40)\n", " custom_layout[\"legend\"] = dict()\n", " custom_layout[\"xaxis\"][\"rangemode\"] = 'normal'\n", " \n", "if output_format == 'CCR':\n", " custom_layout[\"width\"] = linewidth_px\n", " custom_layout[\"height\"] = 225\n", " custom_layout[\"legend\"]['x'] = 1\n", " custom_layout[\"legend\"]['y'] = 0.1\n", " custom_layout[\"legend\"]['yanchor'] = 'bottom'\n", " custom_layout[\"legend\"]['orientation'] = 'v'\n", " custom_layout['margin'] = dict(l=40, r=0, t=0, b=30)\n", "\n", "figure.update_layout(custom_layout)\n", "figure.show()\n", "\n", "# Save plot\n", "if output_format == 'CCR':\n", " figure.write_image(str(plot_path/plot_out_name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Back to top](#TriScale-Interactive-Plots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] } ], "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.9.6" } }, "nbformat": 4, "nbformat_minor": 2 }