{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Plotting notebook\n",
    "\n",
    "This notebook generates plots for paper submission. Prior to running this, make sure to run `temporal_trends` and `vulnerabilities` notebooks to produce necessary CSV files into `RESULTS_DIR` folder."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import scipy.stats as stats\n",
    "import seaborn as sns\n",
    "\n",
    "from sec_certs.dataset import CCDataset\n",
    "\n",
    "RESULTS_DIR = Path(\"./results\")\n",
    "FIGURE_DIR = RESULTS_DIR / \"figures/\"\n",
    "\n",
    "if not FIGURE_DIR.exists():\n",
    "    FIGURE_DIR.mkdir()\n",
    "\n",
    "# matplotlib.use(\"pgf\")\n",
    "sns.set_theme(style=\"white\")\n",
    "plt.rcParams[\"axes.linewidth\"] = 0.5\n",
    "plt.rcParams[\"legend.fontsize\"] = 6.5\n",
    "plt.rcParams[\"xtick.labelsize\"] = 8\n",
    "plt.rcParams[\"ytick.labelsize\"] = 8\n",
    "plt.rcParams[\"ytick.left\"] = True\n",
    "plt.rcParams[\"ytick.major.size\"] = 5\n",
    "plt.rcParams[\"ytick.major.width\"] = 0.5\n",
    "plt.rcParams[\"ytick.major.pad\"] = 0\n",
    "plt.rcParams[\"xtick.bottom\"] = True\n",
    "plt.rcParams[\"xtick.major.size\"] = 5\n",
    "plt.rcParams[\"xtick.major.width\"] = 0.5\n",
    "plt.rcParams[\"xtick.major.pad\"] = 0\n",
    "plt.rcParams[\"pgf.texsystem\"] = \"pdflatex\"\n",
    "plt.rcParams[\"font.family\"] = \"serif\"\n",
    "plt.rcParams[\"text.usetex\"] = True\n",
    "plt.rcParams[\"pgf.rcfonts\"] = False\n",
    "plt.rcParams[\"axes.titlesize\"] = 7\n",
    "plt.rcParams[\"axes.labelsize\"] = 7\n",
    "plt.rcParams[\"legend.handletextpad\"] = 0.3\n",
    "plt.rcParams[\"lines.markersize\"] = 4\n",
    "sns.set_palette(\"deep\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Histogram CVE disclosure dates vs. date of certification"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv(RESULTS_DIR / \"exploded_cves.csv\").rename(columns={\"Unnamed: 0\": \"dgst\"}).set_index(\"dgst\")\n",
    "\n",
    "hist = sns.histplot(df.n_days_after_certification, kde=False)\n",
    "hist.set(\n",
    "    xlim=(-2200, 4600),\n",
    "    ylim=(0, 1800),\n",
    "    xlabel=\"Number of days after date of certification\",\n",
    "    ylabel=\"Frequency of CVEs\",\n",
    ")\n",
    "hist.axvline(0, color=\"red\", linewidth=\"1\", label=\"Certification date\")\n",
    "hist.legend(loc=\"upper right\")\n",
    "\n",
    "fig = matplotlib.pyplot.gcf()\n",
    "fig.set_size_inches(3.35, 2)\n",
    "fig.savefig(FIGURE_DIR / \"cve_hist.pgf\", bbox_inches=\"tight\")\n",
    "fig.savefig(FIGURE_DIR / \"cve_hist.pdf\", bbox_inches=\"tight\")\n",
    "plt.close(fig)\n",
    "\n",
    "# QQ plot of for vulnerability disclosure vs. certification date (compared against normal distribution)\n",
    "# stats.probplot(df.n_days_after_certification, dist=\"norm\", plot=plt)\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Validity boxplot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_validity = pd.read_csv(RESULTS_DIR / \"df_validity.csv\")\n",
    "\n",
    "box = sns.boxplot(data=df_validity, x=\"year_from\", y=\"validity_period\", linewidth=0.75, flierprops={\"marker\": \"x\"})\n",
    "box.set(\n",
    "    xlabel=\"Year of certification\",\n",
    "    ylabel=\"Lifetime of certificates (in years)\",\n",
    "    title=\"Boxplot of certificate validity periods\",\n",
    ")\n",
    "box.tick_params(axis=\"x\", rotation=75)\n",
    "\n",
    "fig = matplotlib.pyplot.gcf()\n",
    "fig.set_size_inches(3.5, 2.5)\n",
    "fig.savefig(FIGURE_DIR / \"boxplot_validity.pgf\", bbox_inches=\"tight\")\n",
    "fig.savefig(FIGURE_DIR / \"boxplot_validity.pdf\", bbox_inches=\"tight\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cells for 3-subplot figure\n",
    "\n",
    "Contains: Average EAL levels, Interesting schemes evolution, Stackplot of categories"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Downloading CC Dataset: 100%|██████████| 164M/164M [02:07<00:00, 1.35MB/s] \n"
     ]
    }
   ],
   "source": [
    "figure_width = 2.3\n",
    "figure_height = 1.8\n",
    "\n",
    "dset = CCDataset.from_web()  # local instantiation\n",
    "df = dset.to_pandas()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "avg_levels = pd.read_csv(RESULTS_DIR / \"avg_eal.csv\")\n",
    "eal_to_num_mapping = {eal: index for index, eal in enumerate(df[\"eal\"].cat.categories)}\n",
    "avg_levels[\"smartcard_category\"] = avg_levels.category.map(\n",
    "    lambda x: x if x == \"ICs, Smartcards\" else \"Other 14 categories\"\n",
    ")\n",
    "line = sns.lineplot(\n",
    "    data=avg_levels,\n",
    "    x=\"year_from\",\n",
    "    y=\"eal_number\",\n",
    "    hue=\"smartcard_category\",\n",
    "    errorbar=None,\n",
    "    style=\"smartcard_category\",\n",
    "    markers=True,\n",
    ")\n",
    "line.set(xlabel=None, ylabel=None, title=None, xlim=(1999.6, 2023.4))\n",
    "ymin = 1\n",
    "ymax = 9\n",
    "ylabels = [\n",
    "    x if \"+\" in x else x + r\"\\phantom{+}\" for x in list(eal_to_num_mapping.keys())[ymin : ymax + 1]\n",
    "]  # this also aligns the labels by adding phantom spaces\n",
    "line.set_yticks(range(ymin, ymax + 1), ylabels)\n",
    "line.set_xticks([1998, 2003, 2008, 2013, 2018, 2023])\n",
    "line.legend(title=None, labels=avg_levels.smartcard_category.unique())\n",
    "\n",
    "fig = matplotlib.pyplot.gcf()\n",
    "fig.set_size_inches(figure_width, figure_height)\n",
    "fig.tight_layout(pad=0.1)\n",
    "fig.savefig(FIGURE_DIR / \"temporal_trends_categories.pgf\")\n",
    "fig.savefig(FIGURE_DIR / \"temporal_trends_categories.pdf\")\n",
    "plt.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "interesting_schemes = pd.read_csv(RESULTS_DIR / \"interesting_schemes.csv\")\n",
    "\n",
    "line = sns.lineplot(\n",
    "    data=interesting_schemes,\n",
    "    x=\"year_from\",\n",
    "    y=\"size\",\n",
    "    hue=\"scheme\",\n",
    "    style=\"scheme\",\n",
    "    markers=True,\n",
    "    dashes=True,\n",
    ")\n",
    "line.set(xlabel=None, ylabel=None, title=None, xlim=(1999.6, 2023.4), ylim=(0, 90))\n",
    "line.set_xticks([1998, 2003, 2008, 2013, 2018, 2023])\n",
    "line.legend(title=None)\n",
    "fig = matplotlib.pyplot.gcf()\n",
    "fig.set_size_inches(figure_width, figure_height)\n",
    "fig.tight_layout(pad=0.1)\n",
    "fig.savefig(FIGURE_DIR / \"temporal_trends_schemes.pgf\")\n",
    "fig.savefig(FIGURE_DIR / \"temporal_trends_schemes.pdf\")\n",
    "plt.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_certs = pd.read_csv(RESULTS_DIR / \"popular_categories.csv\").astype({\"year_from\": \"category\"})\n",
    "dct = {\n",
    "    \"ICs, Smart Cards and Smart Card-Related Devices and Systems\": \"ICs and Smart Cards\",\n",
    "    \"Network and Network-Related Devices and Systems\": \"Network-Related Devices\",\n",
    "    \"Other Devices and Systems\": \"Other Devices\",\n",
    "    \"One of 11 other categories\": \"11 Other Categories\",\n",
    "}\n",
    "n_certs.popular_categories = n_certs.popular_categories.map(lambda x: dct.get(x, x))\n",
    "\n",
    "cats = n_certs.popular_categories.unique()\n",
    "years = n_certs.year_from.cat.categories[:-1]\n",
    "data = [n_certs.loc[n_certs.popular_categories == c, \"size\"].tolist()[:-1] for c in cats]\n",
    "\n",
    "# palette = sns.color_palette(\"Spectral\", 5).as_hex()\n",
    "# colors = \",\".join(palette)\n",
    "\n",
    "plt.stackplot(\n",
    "    years,\n",
    "    data,\n",
    "    labels=cats,\n",
    ")\n",
    "plt.legend(loc=\"upper center\", bbox_to_anchor=(0.38, 1.02))\n",
    "plt.xticks([1998, 2003, 2008, 2013, 2018, 2023])\n",
    "# plt.title(\"(c) Popularity of categories\")\n",
    "plt.xlim(1997, 2023)\n",
    "\n",
    "fig = matplotlib.pyplot.gcf()\n",
    "fig.set_size_inches(figure_width, figure_height)\n",
    "fig.tight_layout(pad=0.1)\n",
    "fig.savefig(FIGURE_DIR / \"temporal_trends_stackplot.pdf\")\n",
    "fig.savefig(FIGURE_DIR / \"temporal_trends_stackplot.pgf\")\n",
    "plt.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.8.13 ('venv': 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.11.5"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "a5b8c5b127d2cfe5bc3a1c933e197485eb9eba25154c3661362401503b4ef9d4"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
