{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Benchmark" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "from sys import argv\n", "rootdir = argv[1]\n", "\n", "#############################\n", "# FOR NOTEBOOK USE #\n", "# SET DIRECTORY HERE #\n", "# #\n", "# rootdir = \"\"\n", "# #\n", "#############################\n", "\n", "print(\"Using root directory: {}\".format(rootdir))\n", "\n", "# Get the subdirs with the different tests\n", "subdirs = sorted([ name for name in os.listdir('{}'.format(rootdir)) if os.path.isdir(os.path.join('{}'.format(rootdir), name)) ])\n", "print(\"Available subdirs: {}\".format(subdirs))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import json\n", "from sys import exit\n", "\n", "with open(\"{}/settings.json\".format(rootdir)) as json_file:\n", " settings = json.load(json_file)\n", "\n", "print(\"Succesfully loaded JSON file\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load all files\n", "A group that will be one line in the summarizing graph is a *node-type* + *mode* combination. This group contains the variable *rate*. See the following three groups as example:\n", "\n", "* InfiniBand (RC): 1KHz, 10KHz, 50KHz, 100KHz\n", "* InfiniBand (UD): 1KHz, 10KHz, 50KHz, 100KHz\n", "* MQTT (UDP): 1KHz, 10KHz, 50KHz\n", "\n", "## Save characteristics of tests\n", "All important settings are contained in the name of the file. We will save them in a separate array. The structure of the name is as follows:\n", "\n", "```bash\n", "root_dir/benchmarks_${DATE}/${ID}_${MODE}-${VALUES IN SMP}-${RATE}-${SENT SMPS}\n", "```\n", "\n", "Thus, we will structure it in the settings_array as follows:\n", "\n", "* `settings_array[*][0] = ID`\n", "* `settings_array[*][1] = MODE`\n", "* `settings_array[*][2] = VALUES IN SAMPLE`\n", "* `settings_array[*][3] = RATE`\n", "* `settings_array[*][4] = TOTAL NUMBER OF SAMPLES`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "import numpy as np\n", "import re\n", "\n", "# First, source log\n", "\n", "# Initialize arrays\n", "input_dataset = []\n", "output_dataset = []\n", "settings_array = []\n", "\n", "\n", "for i, subdir in enumerate(subdirs):\n", " input_dataset.append([])\n", " output_dataset.append([])\n", "\n", " # Acquire node type from the directory\n", " matchObj = re.match(r'(\\w*)_[A-Z]', subdir, re.M|re.I)\n", " \n", " # Fill value to array\n", " if matchObj:\n", " node_type = matchObj[1]\n", "\n", " # Acquire all tests in that subdirectory\n", " for walk_subdir, dirs, files in sorted(os.walk(\"{}/{}\".format(rootdir, subdir))):\n", " input_dataset.append([])\n", " output_dataset.append([])\n", " settings_array.append([])\n", " \n", " for file in sorted(files):\n", " ############################\n", " ###### SAVE SETTINGS #######\n", " ############################\n", " temp_settings = []\n", " temp_settings.append(node_type)\n", " \n", " # Match settings, as described above\n", " matchObj = re.match(r'.*?(\\d*)_(\\w*)-(\\d*)-(\\d*)-(\\d*)_output.csv', file, re.M|re.I)\n", "\n", " # Fill values to array\n", " if matchObj:\n", " for j in range(0,5):\n", " temp_settings.append(matchObj.group(j + 1))\n", " \n", " # Append array to big array\n", " settings_array[i].append(temp_settings)\n", " \n", " ############################\n", " ######### LOAD DATA ########\n", " ############################\n", " \n", " # Regex to match input files\n", " if re.match(r'.*?_input.csv', file, re.M|re.I):\n", " # Load file \n", " input_dataset[i].append(np.genfromtxt(\"{}/{}/{}\".format(rootdir, subdir, file), delimiter=','))\n", " \n", " print(\"Loaded input dataset from: {}\".format(file))\n", "\n", " # Regex to match output files files\n", " elif re.match(r'.*?_output.csv', file, re.M|re.I):\n", " output_dataset[i].append(np.genfromtxt(\"{}/{}/{}\".format(rootdir, subdir, file), delimiter=','))\n", " \n", " print(\"Loaded output dataset from: {}\".format(file))\n", "\n", " print(\"Settings for this subdirectory: \")\n", " print(settings_array[i])\n", " print(\"\\n\")\n", "\n", " # Small sanity check, are arrays of the same size?\n", " if len(input_dataset[i]) != len(output_dataset[i]):\n", " print(\"Error: There should be as many input files as there are output files!\")\n", " exit();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get missed steps from source node\n", "..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Number of missing samples at receive side\n", "missed_send_arr = []\n", "# Percentage of missed samples\n", "perc_miss_send_arr = []\n", "\n", "# Generate real total and number of missing samples.\n", "# Print percentage of missed samples\n", "for i, subdir in enumerate(subdirs):\n", " missed_send_arr.append([])\n", " perc_miss_send_arr.append([])\n", " \n", " for (j, csv_vec) in enumerate(input_dataset[i]):\n", " # Get number of missing samples\n", " missed_send_arr[i].append(int(settings_array[i][j][5]) - len(csv_vec))\n", "\n", " # Take percentage\n", " perc_miss_send_arr[i].append(round(missed_send_arr[i][j] / int(settings_array[i][j][5]) * 100, 2))\n", " \n", " print(\"Test {} ({}) is missing {} ({}%) of {} in in-file.\"\n", " .format(settings_array[i][j][0], settings_array[i][j][2], missed_send_arr[i][j], \n", " perc_miss_send_arr[i][j], settings_array[i][j][5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get missed steps from destination node\n", "..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Number of missing samples at receive side\n", "missed_recv_arr = []\n", "# Percentage of missed samples\n", "perc_miss_recv_arr = []\n", "\n", "# Generate real total and number of missing samples.\n", "# Print percentage of missed samples\n", "for i, subdir in enumerate(subdirs):\n", " missed_recv_arr.append([])\n", " perc_miss_recv_arr.append([])\n", "\n", " for (j, csv_vec) in enumerate(output_dataset[i]):\n", "\n", " # Get number of missing samples\n", " missed_recv_arr[i].append(int(settings_array[i][j][5]) - len(csv_vec))\n", "\n", " # Take percentage\n", " perc_miss_recv_arr[i].append(round(missed_recv_arr[i][j] / int(settings_array[i][j][5]) * 100, 2))\n", "\n", " print(\"Test {} ({}) is missing {} ({}%) of {} in out-file.\"\n", " .format(settings_array[i][j][0], settings_array[i][j][2], missed_recv_arr[i][j], \n", " perc_miss_recv_arr[i][j], settings_array[i][j][5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Check first and second sample from receive & destination node\n", "..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Check first and second sample\n", "\n", "first_second_smp_input = []\n", "first_second_smp_output = []\n", "\n", "for i, subdir in enumerate(subdirs):\n", " first_second_smp_input.append([])\n", " first_second_smp_output.append([])\n", " \n", " for (j, csv_vec) in enumerate(input_dataset[i+1]):\n", " first_second_smp_input[i].append([csv_vec[0][1], csv_vec[1][1]])\n", " print(\"First and second sample of test {} ({}): {} and {}, respectively\".format(settings_array[i][j][0],\n", " settings_array[i][j][2],\n", " int(first_second_smp_input[i][j][0]),\n", " int(first_second_smp_input[i][j][1])))\n", "\n", " for (j, csv_vec) in enumerate(output_dataset[i]):\n", " first_second_smp_output[i].append([csv_vec[0][1], csv_vec[1][1]])\n", " print(\"First and second sample of test {} ({}): {} and {}, respectively\".format(settings_array[i][j][0],\n", " settings_array[i][j][2],\n", " int(first_second_smp_output[i][j][0]),\n", " int(first_second_smp_output[i][j][1])))\n", " \n", " print(\"\")\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compare input and output data sets\n", "..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "missing_seq = []\n", "\n", "never_trans_total_arr = []\n", "never_trans_after_arr = []\n", "\n", "perc_never_trans_total_arr = []\n", "perc_never_trans_after_arr = []\n", "\n", "# Loop through input_array, since this is always bigger or equal to output array\n", "for i, subdir in enumerate(subdirs):\n", " never_trans_total_arr.append([])\n", " never_trans_after_arr.append([])\n", " \n", " perc_never_trans_total_arr.append([])\n", " perc_never_trans_after_arr.append([])\n", " \n", " missing_seq.append([])\n", " \n", " for (j, csv_vec) in enumerate(input_dataset[i]): \n", " l = 0\n", " missing_seq[i].append([])\n", " for (k, line) in enumerate(csv_vec): \n", " try:\n", " if line[1] != output_dataset[i][j][l][1]:\n", " missing_seq[i][j].append(line[1])\n", " else:\n", " l += 1\n", "\n", " except IndexError:\n", " pass\n", "\n", " never_trans_total_arr[i].append(len(missing_seq[i][j]))\n", "\n", " never_trans_after_arr[i].append(np.sum(missing_seq[i][j] > first_second_smp_output[i][j][0]))\n", "\n", " # Take percentage\n", " perc_never_trans_total_arr[i].append(round(never_trans_total_arr[i][j] / int(settings_array[i][j][5]) * 100, 2))\n", " perc_never_trans_after_arr[i].append(round(never_trans_after_arr[i][j] / int(settings_array[i][j][5]) * 100, 2))\n", "\n", " print(\"Test {} ({}): {} ({}%) samples were never transferred \".format(settings_array[i][j][0],\n", " settings_array[i][j][2],\n", " never_trans_total_arr[i][j],\n", " perc_never_trans_total_arr[i][j]))\n", " print(\"{} ({}%) of these after the first sample occured in out-file.\".format(never_trans_after_arr[i][j],\n", " perc_never_trans_after_arr[i][j]))\n", "\n", " print(\"\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate medians" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "medians = []\n", "upper_limit = []\n", "lower_limit = []\n", "\n", "for i, subdir in enumerate(subdirs):\n", " medians.append([])\n", " upper_limit.append([])\n", " lower_limit.append([])\n", "\n", " for (j, csv_vec) in enumerate(output_dataset[i]): \n", " medians[i].append(np.median(csv_vec.transpose()[0]) * 1e6)\n", "\n", " if settings['median_plot']['enabled']:\n", " # np.sort(recv[i][j] - enq_send[i][j])[int(np.size(recv[i][j]]) / 2)] would be the approximately the median\n", " # Calculate upper 10% and lower 10%\n", " upper_limit[i].append(abs(medians[i][j] - 1e6 * np.sort(csv_vec.transpose()[0])[int(9 * np.size(csv_vec.transpose()[0]) / 10)]))\n", " lower_limit[i].append(abs(medians[i][j] - 1e6 * np.sort(csv_vec.transpose()[0])[int(1 * np.size(csv_vec.transpose()[0]) / 10)]))" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Plot data\n", "### First, define some functions" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Define Fancy Box function we use\n", "def plot_fancy_box(bottom, height, ax):\n", " top = bottom + height\n", " \n", " p = FancyBboxPatch((left, bottom),\n", " width,\n", " height,\n", " boxstyle=\"round, pad=0.005\",\n", " \n", " ec=\"#dbdbdb\", \n", " fc=\"white\", \n", " alpha=0.85,\n", " transform=ax.transAxes\n", " )\n", " ax.add_patch(p)\n", " \n", " \n", "# Define \"find nearest\" function\n", "def find_nearest(array, value):\n", " array = np.asarray(array)\n", " idx = (np.abs(array - value)).argmin()\n", " return array[idx], idx" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Import all necessary libraries to plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "from matplotlib.font_manager import FontProperties\n", "from matplotlib.patches import FancyBboxPatch\n", "from matplotlib.ticker import MultipleLocator\n", "import pylab \n", "from mpl_toolkits.mplot3d import Axes3D\n", "import matplotlib.pyplot as plt\n", "from matplotlib import cm\n", "from matplotlib.ticker import LinearLocator, FormatStrFormatter\n", "import matplotlib as mpl\n", "import matplotlib.legend as mlegend" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Start with histograms if they are enabled" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "if settings['histograms']['enabled']:\n", " for i, subdir in enumerate(subdirs):\n", " for (j, csv_vec) in enumerate(output_dataset[i]):\n", " # Create figure\n", " fig = plt.figure(num=None, figsize=(12, 4), dpi=90, facecolor='w', edgecolor='k')\n", "\n", " # Add plot and set title\n", " ax = fig.add_subplot(111)\n", "\n", " # Set grid\n", " ax.set_axisbelow(True)\n", " ax.grid(True, linestyle='--')\n", "\n", " x_limit = 0.00005\n", " bins = np.arange(0, 50, 50 / 100)\n", "\n", " # Data in plot\n", " # http://www.color-hex.com/color-palette/33602\n", " csv_vec_t = csv_vec.transpose()\n", "\n", " ax.hist(csv_vec_t[0] * 1e6, label=settings['histograms']['labels'][0],\n", " edgecolor='black',\n", " bins=bins,\n", " color='#00549f')\n", " ax.axvline(medians[i][j], color='red', linestyle='-', linewidth=1, alpha=0.85)\n", "\n", " # Set axis and calculate values above limit\n", " plt.xlim([0,x_limit])\n", "\n", " ###################################\n", " # SET TICKS #######################\n", " ###################################\n", " ticks = np.arange(0, x_limit * 1e6 + 1, 2)\n", "\n", " nearest, nearest_idx = find_nearest(ticks, medians[i][j])\n", " \n", " ticks = np.append(ticks, medians[i][j])\n", "\n", " # Explicitly set labels\n", " labels = []\n", "\n", " for value in ticks:\n", " if value == nearest and np.abs(nearest - medians[i][j]) < 200:\n", " labels.append(\"\")\n", " elif value == (medians[i][j]):\n", " labels.append(\"{:5.3f}\".format(value))\n", " else:\n", " labels.append(str(int(value)))\n", "\n", " plt.yticks(fontsize=10, family='monospace')\n", " plt.xticks(ticks, labels, fontsize=10, family='monospace', rotation=30, horizontalalignment='right', rotation_mode=\"anchor\")\n", "\n", " for value in ax.get_xticklabels():\n", " try:\n", " if int(float(value.get_text())) == int(medians[i][j]):\n", " value.set_color('red')\n", " except ValueError:\n", " # We got some empty values. Ignore them\n", " pass\n", "\n", " minorLocator = MultipleLocator(1)\n", " ax.xaxis.set_minor_locator(minorLocator)\n", "\n", " ###################################\n", " # CONFIGURE AXIS ##################\n", " ###################################\n", " # Set labels\n", " ax.set_xlabel(settings['histograms']['axis_labels']['x'], fontsize=10, family='monospace', labelpad = 4)\n", " ax.set_ylabel(settings['histograms']['axis_labels']['y'], fontsize=10, family='monospace', labelpad = 6)\n", " \n", " # Set scale\n", " ax.set_yscale('log')\n", "\n", " ###################################\n", " # CREATE TEXTBOXES ################\n", " ###################################\n", " off_bigger_50us = round((np.size(csv_vec_t[0][csv_vec_t[0] > x_limit]) / np.size(csv_vec_t[0])) * 100, 2)\n", "\n", " offset_text = '$\\mathtt{{t_{{lat}}>50µs: }}${0: >5.2f}% ($\\mathtt{{\\\\max\\\\,t_{{lat}}}}$: {1:>7.2f}µs)'.format(off_bigger_50us, round(np.max(csv_vec_t[0]) * 1e6, 2))\n", "\n", " # Create text for missed steps\n", " missed_text = ' in: {0:6d} ({1:5.2f}%)\\n'.format(missed_send_arr[i][j], perc_miss_send_arr[i][j])\n", " missed_text += 'out: {0:6d} ({1:5.2f}%)'.format(missed_recv_arr[i][j], perc_miss_recv_arr[i][j])\n", "\n", " # Create text for missed steps\n", " never_transferred_text = 'total: {0:5d} ({1:5.2f}%)\\n'.format(never_trans_total_arr[i][j], perc_never_trans_total_arr[i][j])\n", " never_transferred_text += 'while connected: {0:5d} ({1:5.2f}%)'.format(never_trans_after_arr[i][j], perc_never_trans_after_arr[i][j])\n", "\n", " # Set font properties for headers and text\n", " font_header = FontProperties()\n", " font_header.set_family('monospace')\n", " font_header.set_weight('bold')\n", " font_header.set_size(9.5)\n", "\n", " font_text = FontProperties()\n", " font_text.set_size(9.5)\n", " font_text.set_family('monospace')\n", "\n", " # Set box constraints for wrapper and plot wrapper\n", " left, width = .673, .33\n", " right = left + width\n", "\n", " plot_fancy_box(bottom = 0.46, height = 0.65, ax = ax)\n", "\n", " # Set box constraints for text boxes\n", " left, width = .685, .30\n", " right = left + width\n", "\n", " # Offset boxes\n", " plot_fancy_box(bottom = 0.9085, height = 0.085, ax = ax)\n", "\n", " ax.text(right, 0.975, offset_text,\n", " verticalalignment='top', horizontalalignment='right',\n", " transform=ax.transAxes,\n", " color='black', fontproperties = font_text)\n", "\n", " # Missed steps\n", " plot_fancy_box(bottom = 0.695, height = 0.18, ax = ax)\n", "\n", " ax.text(right, 0.868, \"missing samples:\",\n", " verticalalignment='top', horizontalalignment='right',\n", " transform=ax.transAxes,\n", " color='black', fontproperties = font_header)\n", " ax.text(right, 0.804, missed_text,\n", " verticalalignment='top', horizontalalignment='right',\n", " transform=ax.transAxes,\n", " color='black', fontproperties = font_text)\n", "\n", " # Never transferred\n", " plot_fancy_box(bottom = 0.487, height = 0.175, ax = ax)\n", "\n", " ax.text(right, 0.657, \"samples not transmitted:\",\n", " verticalalignment='top', horizontalalignment='right',\n", " transform=ax.transAxes,\n", " color='black', fontproperties = font_header)\n", " ax.text(right, 0.593, never_transferred_text,\n", " verticalalignment='top', \n", " horizontalalignment='right',\n", " transform=ax.transAxes,\n", " color='black', fontproperties = font_text)\n", "\n", "\n", " ###################################\n", " # SAVE PLOT #######################\n", " ###################################\n", " plt.minorticks_on()\n", " plt.tight_layout()\n", "\n", " fig.savefig('{}/{}_{}_{}i_{}j.pdf'.format(rootdir, \n", " settings_array[i][j][0], \n", " settings_array[i][j][2], i, j),\n", " format='pdf') \n", "\n", " ###################################\n", " # CREATE HISTOGRAM LEGEND #########\n", " ###################################\n", " # create a second figure for the legend\n", " figLegend = pylab.figure(figsize = settings['histograms']['dimensions']['legend'])\n", "\n", " # produce a legend for the objects in the other figure\n", " pylab.figlegend(*ax.get_legend_handles_labels(), loc = 'upper left',\n", " prop={'family':'monospace', 'size':'8'}, \n", " ncol=settings['histograms']['legend_columns'])\n", " \n", " figLegend.savefig(\"{}/histogram_legend.pdf\".format(rootdir), format='pdf')\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if settings['median_plot']['enabled']:\n", " # Create figure and axis\n", " fig_median = plt.figure(num=None, figsize=(12, 4), dpi=90, facecolor='w', edgecolor='k')\n", " ax_median = fig_median.add_subplot(111)\n", "\n", " for i, subdir in enumerate(subdirs):\n", "\n", " ###################################\n", " # CREATE MEDIAN PLOT ##############\n", " ###################################\n", " x_data = np.array([])\n", " for k in range(0, len(medians[i])):\n", " x_data = np.append(x_data, k)\n", " \n", " try:\n", " marker = settings['median_plot']['markers'][i]\n", " except KeyError:\n", " marker = 'v'\n", "\n", " ax_median.errorbar(x_data, medians[i], yerr=[lower_limit[i], upper_limit[i]],\n", " capsize = 3.7, elinewidth = 1, markeredgewidth = 1, \n", " marker=marker, zorder = 2 + i, color=settings['median_plot']['colors'][i],\n", " label=settings['median_plot']['labels'][i])\n", "\n", " ###################################\n", " # PRINT MISSED STEPS ##############\n", " ###################################\n", " if settings['median_plot']['print_missed_steps']:\n", " for l, median in enumerate(medians[i]):\n", " \n", " p = FancyBboxPatch((x_data[l] + 0.07, median + 0.08), 0.345, 0.29, boxstyle=\"round, pad=0.005\",\n", " ec=\"#dbdbdb\", fc=\"white\", alpha=0.85)\n", " ax_median.add_patch(p)\n", " \n", " ax_median.text(x_data[l] + 0.1, median + 0.15, \"{: >4.2f}%\".format(perc_miss_recv_arr[i][l]))\n", " \n", " # Create bbox patch for legend\n", " #p = FancyBboxPatch((0, 0), 5, 1, boxstyle=\"round, pad=0.5\", ec=\"#dbdbdb\", fc=\"white\", alpha=0.85)\n", " \n", " handles = []\n", " handles.append(p)\n", " text= '% of samples missed by signal generator'\n", " leg2 = mlegend.Legend(ax_median, handles, labels=[text], loc = 'upper left', ncol=1,\n", " prop={'family':'monospace', 'size':'8'})\n", "\n", " \n", " \n", " ###################################\n", " # SET AXIS OF MEDIAN PLOT #########\n", " ###################################\n", " ax_median.set_xticks(np.arange(0, len(settings['median_plot']['ticks']['x']), 1))\n", " ax_median.set_xticklabels(settings['median_plot']['ticks']['x'])\n", " \n", " if settings['median_plot']['log_scale']:\n", " ax_median.set_yscale('log')\n", " else:\n", " ax_median.set_ylim([settings['median_plot']['ticks']['y'][0], settings['median_plot']['ticks']['y'][-1]])\n", " ax_median.set_yticks(settings['median_plot']['ticks']['y'])\n", " \n", " ax_median.set_xlabel(settings['median_plot']['axis_labels']['x'], fontsize=11, family='monospace', labelpad=6)\n", " ax_median.set_ylabel(settings['median_plot']['axis_labels']['y'], fontsize=11, family='monospace', labelpad=6)\n", " ax_median.set_axisbelow(True)\n", " ax_median.grid(True, linestyle='--')\n", "\n", " ax_median.yaxis.grid(True, linestyle='-', which='major', color='black', alpha=0.8)\n", " ax_median.yaxis.grid(True, linestyle='--', which='minor', color='lightgrey', alpha=0.3)\n", "\n", " ###################################\n", " # EXPORT MEDIANS AND CREATE #######\n", " # LEGEND OF MEDIAN TABLE ##########\n", " ###################################\n", " plt.tight_layout()\n", " fig_median.savefig('{}/median_graph.pdf'.format(rootdir), dpi=600, format='pdf', bbox_inches='tight')\n", "\n", " # create a second figure for the legend\n", " figLegend = pylab.figure(figsize = settings['median_plot']['dimensions']['legend'])\n", " \n", "\n", " leg_temp = pylab.figlegend(*ax_median.get_legend_handles_labels(), loc = 'upper left', labelspacing=1.2,\n", " prop={'family':'monospace', 'size':'8'}, ncol=settings['median_plot']['legend_columns'])\n", " \n", " if settings['median_plot']['print_missed_steps']:\n", " leg_temp._legend_box._children.append(leg2._legend_box._children[1])\n", " leg_temp._legend_box.align=\"left\"\n", " \n", " figLegend.savefig(\"{}/median_legend.pdf\".format(rootdir), format='pdf')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create 3D-Plot if enabled" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "if settings['3d_plot']['enabled']:\n", " for i, subdir in enumerate(subdirs):\n", " fig_3d = plt.figure(num=None, figsize=(16, 7), dpi=90, facecolor='w', edgecolor='k')\n", " ax_3d = fig_3d.gca(projection='3d')\n", " plt.tight_layout()\n", "\n", " # Make data.\n", " X = np.array([])\n", " for k in range(0, len(settings['3d_plot']['ticks']['x'])):\n", " X = np.append(X, k)\n", "\n", " Y = np.array([])\n", " for k in range(0, len(settings['3d_plot']['ticks']['y'])):\n", " Y = np.append(Y, k)\n", "\n", " X, Y = np.meshgrid(X, Y)\n", "\n", " Z = np.array([])\n", " for k in range(0, len(settings['3d_plot']['ticks']['y'])):\n", " for l in range(0, len(settings['3d_plot']['ticks']['x'])):\n", " Z = np.append(Z, medians[i][k * len(settings['3d_plot']['ticks']['x']) + l])\n", " \n", " ###################################\n", " # PRINT MISSED STEPS ##############\n", " # CIRCLE MAXIMUM AND MINIMUM ######\n", " ###################################\n", " \n", " for k in range(0, len(input_dataset[i])):\n", " # Circle maximum and minimum\n", " if Z[k] == np.min(Z):\n", " props = dict(boxstyle='round', pad=0.35, facecolor='white', edgecolor='green', linewidth=4, alpha=1)\n", " elif Z[k] == np.max(Z):\n", " props = dict(boxstyle='round', pad=0.35, facecolor='white', edgecolor='red', linewidth=4, alpha=1)\n", " else:\n", " props = dict(boxstyle='round', pad=0.25, facecolor='white', edgecolor='black', linewidth=1.5, alpha=1)\n", " \n", " # Calculate X, Y, Z coordinates\n", " x = k % (len(settings['3d_plot']['ticks']['x']))\n", " y = np.floor(k / (len(settings['3d_plot']['ticks']['y'])))\n", " z = Z[k]\n", " \n", " # Move box and set color of text\n", " if perc_miss_send_arr[i][k] > 10:\n", " x_delta = 0.14\n", " color = 'red'\n", " else:\n", " x_delta = 0.07\n", " color = 'black'\n", " \n", " y_delta = 0.1\n", " z_delta = 0\n", " ax_3d.text(x - x_delta, y - y_delta, z - z_delta, \"{}%\".format(int(perc_miss_send_arr[i][k])), \n", " fontsize=11, family='monospace', color=color, bbox=props,zorder=1000)\n", "\n", " Z = Z.reshape(len(settings['3d_plot']['ticks']['x']),len(settings['3d_plot']['ticks']['y']))\n", "\n", " # Plot the surface.\n", " surf = ax_3d.plot_surface(X, Y, Z, cmap=cm.Blues, linewidth=135, antialiased=False, shade=True)\n", " ax_3d.plot_wireframe(X, Y, Z, 10, lw=1, colors=\"k\", linestyles=\"solid\")\n", "\n", " # Customize the z axis.\n", " ax_3d.set_zlim(0, settings['3d_plot']['ticks']['z'][-1])\n", " ax_3d.zaxis.set_major_locator(LinearLocator(10))\n", "\n", " ax_3d.set_xlabel(settings['3d_plot']['axis_labels']['x'], fontsize=11, family='monospace', labelpad=14)\n", " ax_3d.set_ylabel(settings['3d_plot']['axis_labels']['y'], fontsize=11, family='monospace', labelpad=8)\n", " ax_3d.set_zlabel(settings['3d_plot']['axis_labels']['z'], fontsize=11, family='monospace', labelpad=8)\n", "\n", " ax_3d.set_xticks(np.arange(0, len(settings['3d_plot']['ticks']['x']), 1))\n", " ax_3d.set_xticklabels(settings['3d_plot']['ticks']['x'])\n", "\n", " ax_3d.set_yticklabels(settings['3d_plot']['ticks']['y'])\n", " ax_3d.set_zticks(np.arange(0, len(settings['3d_plot']['ticks']['z']), 1))\n", "\n", " norm = mpl.colors.Normalize(vmin=np.min(Z), vmax=np.max(Z))\n", " cb = fig_3d.colorbar(surf, shrink=0.8, aspect=10, fraction=0.1, norm=norm)\n", " cb.set_label(settings['3d_plot']['axis_labels']['z'], fontsize=11, family='monospace', labelpad=8)\n", " \n", " fig_3d.savefig('{}/median_3d_graph_{}.pdf'.format(rootdir, settings_array[i][0][2]), format='pdf', dpi=600)\n", " \n", " ###################################\n", " # CREATE LEGEND ###################\n", " ###################################\n", " # create a second figure for the legend\n", " figLegend = pylab.figure(figsize = settings['3d_plot']['dimensions']['legend'])\n", "\n", " # The markers are too big, so lets create smaller markers\n", " ax_custom = figLegend.add_subplot(111)\n", " ax_custom.plot(0,0, marker='s', color = 'green', label=\"$\\\\min\\\\,\\\\tilde{{t}}_{{lat}}$: {:5.3f} µs\".format(np.min(Z)), markersize=8, linestyle = 'None')\n", " ax_custom.plot(0,0, marker='s', color = 'red', label=\"$\\\\max\\\\,\\\\tilde{{t}}_{{lat}}$: {:5.3f} µs\".format(np.max(Z)), markersize=8, linestyle = 'None')\n", " ax_custom.set_visible(False)\n", "\n", " # Create bbox patch for legend\n", " p = FancyBboxPatch((0, 0), 5, 1, boxstyle=\"round, pad=0.5\", ec=\"#dbdbdb\", fc=\"white\", edgecolor='red',alpha=1)\n", " \n", " handles = []\n", " handles.append(p)\n", " text= '% of samples missed by signal generator'\n", " leg2 = mlegend.Legend(ax_custom, handles, labels=[text], loc = 'upper left', ncol=1,\n", " prop={'family':'monospace', 'size':'8'})\n", "\n", " # Extract handles from pseudo plot\n", " handles, labels = ax_custom.get_legend_handles_labels()\n", "\n", " leg_temp = pylab.figlegend(handles, labels, loc = 'upper left', labelspacing=1.2,\n", " prop={'family':'monospace', 'size':'8'}, ncol=settings['3d_plot']['legend_columns'])\n", " \n", " # Concat handles\n", " leg_temp._legend_box._children.append(leg2._legend_box._children[1])\n", " leg_temp._legend_box.align=\"left\"\n", " \n", " # Save figure\n", " figLegend.savefig(\"{}/3d_{}_legend.pdf\".format(rootdir, settings_array[i][0][2]), format='pdf')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "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.7.1" } }, "nbformat": 4, "nbformat_minor": 2 }