{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Maximal Mediated Sets Database Tutorial\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os # for listing directory entries\n",
    "import pandas as pd # for dataframes\n",
    "import numpy as np\n",
    "from fractions import Fraction # for rational numbers\n",
    "import matplotlib.pyplot as plt # for pics\n",
    "from statsmodels.stats.weightstats import DescrStatsW # for statistics on counts vectors \n",
    "# You can run \"pip install statsmodels\" from terminal to install statsmodels. \n",
    "import re # for regex "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is jupyter notebook covers how to analyze the database of maximal mediated sets. The database and this tutorial are accompanying to the paper \"Initial Steps in the Classifications of Maximal Mediated Sets\". The database was created using _Polymake_ extension __max_mediated_sets__, see [this link](https://polymake.org/doku.php/extensions/max_mediated_sets) for further information on the extension.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The database is divided into smaller datasets according to three parameters; $n$, $2d$ and $rnd$. $n$ corresponds to the dimension of the simplicial sets, $2d$ corresponds to the allowed maximum 1-norm. Lastly, $rnd$ indicates whether dataset contains all simplical sets for the given $n$ and $2d$ or dataset is sampled.\n",
    "\n",
    "For the fully computed datasets, we stored the data corresponding to the <b><span style=\"color:red\">n</span></b>-simplicial sets with maximum degree <b><span style=\"color:red\">2d</span></b> under the database file with name *MMS_dim<b><span style=\"color:red\">n</span></b>_deg<b><span style=\"color:red\">2d</span></b>.db.csv.gz*. \n",
    "The following table shows the available $n$ and $2d$.\n",
    "\n",
    "| n | 2d |\n",
    "| ----------- | ----------------- |\n",
    "| 2 | 50,100,150 |\n",
    "| 3 | 10, 16 |\n",
    "| 4 | 10, 12, 14 |\n",
    "| 5 | 8 |\n",
    "| 7 | 4 |\n",
    "\n",
    "For sampled datasets, we stored the data corresponding to the b><span style=\"color:red\">n</span></b>-simplicial sets with maximum degree $2d$ under the database file with name *MMS_dim<b><span style=\"color:red\">n</span></b>_deg<b><span style=\"color:red\">2d</span></b>*_*<b><span style=\"color:red\">rnd</span></b>.db.csv.gz*. \n",
    "The following table shows the available $n$ and $2d$.\n",
    "\n",
    "| n | 2d |\n",
    "| ----------- | ----------------- |\n",
    "| 5 |  16 |\n",
    "| 6 | 16, 20 |\n",
    "| 7 | 16 |\n",
    "| 8 | 16 |\n",
    "| 9 | 16 |\n",
    "\n",
    "\n",
    "You can navigate the database by loading the data of<span style=\"color:blue\">MMS_dimn*_*deg2d.db.csv.gz</span> or check the statistics for the corresponding part of the database by loading <span style=\"color:blue\">MMS_dimn_deg2d.db.hist</span>.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Navigating the Database"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us say that we want to see the data corresponding to the 3-simplicial sets with maximum degree 16. Then we load data by calling the Pandas method <span style=\"color:blue\">read_csv</span>.\n",
    "Note that this loads everything to RAM, thus it might cause some troubles for larger db.csv.gz files. See the next section for how to analyze the database statistics in this case."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>hnf</th>\n",
       "      <th>h_ratio</th>\n",
       "      <th>mms</th>\n",
       "      <th>companions</th>\n",
       "      <th>n_companions</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[[16,0,0],[2,14,0],[2,0,8]]</td>\n",
       "      <td>1</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,0,...</td>\n",
       "      <td>[[0,1,0],[0,0,1],[1,0,0]],[[0,0,1],[0,1,0],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[[2,0,0],[2,4,0],[16,22,34]]</td>\n",
       "      <td>1/12</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[16,22,34],[9...</td>\n",
       "      <td>[[3,4,7],[-4,-5,-10],[1,1,2]],[[1,1,2],[2,4,5]...</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[[4,0,0],[6,14,0],[0,4,10]]</td>\n",
       "      <td>17/53</td>\n",
       "      <td>[[0,0,0],[0,4,10],[2,0,0],[2,2,0],[2,4,0],[4,0...</td>\n",
       "      <td>[[0,1,1],[0,-1,0],[1,3,0]],[[0,1,1],[1,3,0],[0...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>[[6,0,0],[0,2,0],[14,24,38]]</td>\n",
       "      <td>5/6</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,4,4],[4,0,...</td>\n",
       "      <td>[[2,3,5],[-1,-1,-2],[1,0,0]],[[-1,-1,-2],[2,3,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>[[6,0,0],[2,6,0],[12,2,14]]</td>\n",
       "      <td>60/89</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...</td>\n",
       "      <td>[[1,0,1],[-1,1,0],[1,0,0]],[[-1,1,0],[1,0,1],[...</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                            hnf h_ratio  \\\n",
       "0   [[16,0,0],[2,14,0],[2,0,8]]       1   \n",
       "1  [[2,0,0],[2,4,0],[16,22,34]]    1/12   \n",
       "2   [[4,0,0],[6,14,0],[0,4,10]]   17/53   \n",
       "3  [[6,0,0],[0,2,0],[14,24,38]]     5/6   \n",
       "4   [[6,0,0],[2,6,0],[12,2,14]]   60/89   \n",
       "\n",
       "                                                 mms  \\\n",
       "0  [[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,0,...   \n",
       "1  [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[16,22,34],[9...   \n",
       "2  [[0,0,0],[0,4,10],[2,0,0],[2,2,0],[2,4,0],[4,0...   \n",
       "3  [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,4,4],[4,0,...   \n",
       "4  [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...   \n",
       "\n",
       "                                          companions  n_companions  \n",
       "0  [[0,1,0],[0,0,1],[1,0,0]],[[0,0,1],[0,1,0],[1,...             6  \n",
       "1  [[3,4,7],[-4,-5,-10],[1,1,2]],[[1,1,2],[2,4,5]...            12  \n",
       "2  [[0,1,1],[0,-1,0],[1,3,0]],[[0,1,1],[1,3,0],[0...             6  \n",
       "3  [[2,3,5],[-1,-1,-2],[1,0,0]],[[-1,-1,-2],[2,3,...             6  \n",
       "4  [[1,0,1],[-1,1,0],[1,0,0]],[[-1,1,0],[1,0,1],[...            12  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file = \"MMS_dim3_deg16.db.csv.gz\"\n",
    "df = pd.read_csv(\"csv/\"+file,\n",
    "                 names = [\"hnf\", \"h_ratio\", \"mms\", \"companions\", \"n_companions\"],\n",
    "                 # parse ratio as rationals...\n",
    "       \n",
    "                 converters={\"h_ratio\" : lambda v: abs(Fraction(v))},\n",
    "                 compression='gzip', delimiter=';', header=None, encoding='latin1')\n",
    "df.head() # Check the first few entries in the dataframe."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can reach the entries in the database one by one using the keys of the dataframe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "hnf                                   [[16,0,0],[2,14,0],[2,0,8]]\n",
       "h_ratio                                                         1\n",
       "mms             [[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,0,...\n",
       "companions      [[0,1,0],[0,0,1],[1,0,0]],[[0,0,1],[0,1,0],[1,...\n",
       "n_companions                                                    6\n",
       "Name: 0, dtype: object"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.iloc[0] "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In each row the following information is encoded:\n",
    "\n",
    "* **hnf** corresponds to the representative unique hermite normal form. </br> \n",
    "* **h_ratio** corresponds to the $h$-ratio of the simplicial sets that reduce to the same Hermite Normal Form. \n",
    "* **mms** is the maximal mediated set of the simplical set that is given by **hnf**. \n",
    "* **companions** is the set of compainon matrices. If the matrix $M_{\\Delta}$ arising from the simplicial set $\\Delta$ (link to paper) has Hermite Normal Form $H$ then the companion matrix of $\\Delta$ is the matrix $C$ such that $H = M_{\\Delta} C$. \n",
    "* **n_companions** corresponds to the number of different simplicial sets that reduces to same Hermite Normal Form.\n",
    "\n",
    "We can use the functionality of Pandas dataframe to inspect the database, for example one can ask for the simplicial sets whose $h$-ratio is in the interval $(0.5,0.75)$ as follows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>hnf</th>\n",
       "      <th>h_ratio</th>\n",
       "      <th>mms</th>\n",
       "      <th>companions</th>\n",
       "      <th>n_companions</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>[[6,0,0],[0,2,0],[14,24,38]]</td>\n",
       "      <td>5/6</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,4,4],[4,0,...</td>\n",
       "      <td>[[2,3,5],[-1,-1,-2],[1,0,0]],[[-1,-1,-2],[2,3,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>[[6,0,0],[2,6,0],[12,2,14]]</td>\n",
       "      <td>60/89</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...</td>\n",
       "      <td>[[1,0,1],[-1,1,0],[1,0,0]],[[-1,1,0],[1,0,1],[...</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>[[2,0,0],[18,22,0],[4,6,8]]</td>\n",
       "      <td>26/35</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[4,4,0],[4,6,8],[6,6,...</td>\n",
       "      <td>[[2,3,1],[3,4,0],[-2,-3,0]],[[3,4,0],[-2,-3,0]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>[[6,0,0],[0,2,0],[10,34,56]]</td>\n",
       "      <td>88/113</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,4,6],[2,6,8],[4,0,...</td>\n",
       "      <td>[[0,-3,-5],[0,2,3],[1,3,5]],[[0,2,3],[0,-3,-5]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>[[2,0,0],[14,18,0],[2,0,8]]</td>\n",
       "      <td>67/70</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,0,...</td>\n",
       "      <td>[[-2,-3,1],[-2,-3,0],[3,4,0]],[[-2,-3,1],[3,4,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>[[4,0,0],[2,6,0],[14,2,16]]</td>\n",
       "      <td>72/77</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...</td>\n",
       "      <td>[[-2,0,-3],[3,1,4],[1,0,1]],[[0,0,-1],[0,1,1],...</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>[[4,0,0],[0,2,0],[56,6,80]]</td>\n",
       "      <td>93/113</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[4,0,0],[6,2,8],[8,2,...</td>\n",
       "      <td>[[1,0,1],[8,1,12],[-2,0,-3]],[[8,1,12],[-2,0,-...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>[[4,0,0],[6,16,0],[2,4,6]]</td>\n",
       "      <td>25/27</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,0,1],[0,-1,0],[1,3,0]],[[-1,-3,1],[0,-1,0]...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>[[2,0,0],[2,8,0],[32,30,48]]</td>\n",
       "      <td>117/137</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,6,...</td>\n",
       "      <td>[[-3,-2,-5],[2,1,3],[2,2,3]],[[2,1,3],[-3,-2,-...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>[[4,0,0],[4,6,0],[0,2,8]]</td>\n",
       "      <td>39/43</td>\n",
       "      <td>[[0,0,0],[0,2,8],[2,0,0],[2,2,0],[2,2,2],[2,2,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,0,1],[-1,1,0],[1...</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>[[14,0,0],[0,4,0],[8,10,18]]</td>\n",
       "      <td>161/187</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...</td>\n",
       "      <td>[[-1,0,-1],[1,1,2],[1,0,0]],[[1,1,2],[-1,0,-1]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>[[2,0,0],[0,2,0],[212,64,266]]</td>\n",
       "      <td>155/178</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,2,4],[6,2,...</td>\n",
       "      <td>[[-4,-1,-5],[-3,-1,-4],[23,7,29]],[[-4,-1,-5],...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>[[8,0,0],[2,6,0],[4,2,10]]</td>\n",
       "      <td>83/99</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>[[10,0,0],[2,8,0],[4,4,6]]</td>\n",
       "      <td>106/111</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,6,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>[[2,0,0],[2,4,0],[30,8,44]]</td>\n",
       "      <td>31/33</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[4,2,4],[6,2,...</td>\n",
       "      <td>[[4,1,6],[-3,0,-5],[2,0,3]],[[4,1,6],[2,0,3],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31</th>\n",
       "      <td>[[6,0,0],[0,2,0],[12,14,54]]</td>\n",
       "      <td>35/54</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,6],[4,0,0],[4,2,...</td>\n",
       "      <td>[[1,1,4],[-1,0,-1],[1,0,0]],[[-1,0,-1],[1,1,4]...</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35</th>\n",
       "      <td>[[2,0,0],[12,14,0],[8,6,12]]</td>\n",
       "      <td>11/17</td>\n",
       "      <td>[[0,0,0],[2,0,0],[4,2,4],[4,4,2],[6,4,8],[6,6,...</td>\n",
       "      <td>[[3,4,0],[-2,-3,0],[1,1,1]],[[1,1,1],[3,4,0],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>38</th>\n",
       "      <td>[[4,0,0],[0,4,0],[50,12,74]]</td>\n",
       "      <td>139/196</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...</td>\n",
       "      <td>[[-2,0,-3],[1,0,1],[4,1,6]],[[1,0,1],[4,1,6],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>41</th>\n",
       "      <td>[[2,0,0],[2,4,0],[72,56,82]]</td>\n",
       "      <td>79/108</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[10,8,10],[12...</td>\n",
       "      <td>[[13,10,15],[-5,-4,-6],[1,1,1]],[[1,1,1],[13,1...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>44</th>\n",
       "      <td>[[14,0,0],[0,4,0],[2,12,34]]</td>\n",
       "      <td>23/25</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...</td>\n",
       "      <td>[[0,0,-1],[0,1,3],[1,0,0]],[[0,1,3],[0,0,-1],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>49</th>\n",
       "      <td>[[8,0,0],[0,2,0],[22,10,26]]</td>\n",
       "      <td>32/39</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...</td>\n",
       "      <td>[[3,1,3],[-2,0,-1],[1,0,0]],[[-2,0,-1],[3,1,3]...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>55</th>\n",
       "      <td>[[4,0,0],[2,4,0],[10,20,54]]</td>\n",
       "      <td>163/172</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,4,...</td>\n",
       "      <td>[[0,-1,-3],[1,2,6],[0,0,-1]],[[0,0,-1],[1,2,6]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>58</th>\n",
       "      <td>[[2,0,0],[22,36,0],[4,2,6]]</td>\n",
       "      <td>9/10</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[4,2,6],[4,4,0],[4,6,...</td>\n",
       "      <td>[[3,5,0],[-1,-2,0],[1,1,1]],[[1,1,1],[-1,-2,0]...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>[[2,0,0],[26,34,0],[4,4,6]]</td>\n",
       "      <td>19/21</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[4,4,0],[4,4,...</td>\n",
       "      <td>[[0,0,1],[-2,-3,0],[3,4,0]],[[0,0,1],[3,4,0],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>60</th>\n",
       "      <td>[[4,0,0],[0,2,0],[16,50,72]]</td>\n",
       "      <td>97/103</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,4,4],[2,6,...</td>\n",
       "      <td>[[1,5,7],[-1,-4,-6],[1,2,3]],[[-1,-4,-6],[1,5,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>61</th>\n",
       "      <td>[[6,0,0],[0,2,0],[26,14,40]]</td>\n",
       "      <td>62/79</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...</td>\n",
       "      <td>[[2,1,3],[-1,0,-1],[1,0,0]],[[-1,0,-1],[2,1,3]...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>69</th>\n",
       "      <td>[[6,0,0],[2,4,0],[0,10,18]]</td>\n",
       "      <td>64/77</td>\n",
       "      <td>[[0,0,0],[0,10,18],[2,0,0],[2,2,0],[2,2,2],[2,...</td>\n",
       "      <td>[[0,0,-1],[0,1,2],[1,0,0]],[[0,1,2],[0,0,-1],[...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>72</th>\n",
       "      <td>[[14,0,0],[4,10,0],[0,2,14]]</td>\n",
       "      <td>175/184</td>\n",
       "      <td>[[0,0,0],[0,2,14],[2,0,0],[2,2,0],[2,2,2],[2,2...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>74</th>\n",
       "      <td>[[6,0,0],[4,12,0],[2,2,8]]</td>\n",
       "      <td>53/59</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75</th>\n",
       "      <td>[[12,0,0],[4,10,0],[2,2,8]]</td>\n",
       "      <td>193/198</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20343</th>\n",
       "      <td>[[8,0,0],[4,10,0],[2,6,8]]</td>\n",
       "      <td>15/16</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20344</th>\n",
       "      <td>[[14,0,0],[4,8,0],[2,2,12]]</td>\n",
       "      <td>245/256</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20347</th>\n",
       "      <td>[[2,0,0],[18,22,0],[8,2,10]]</td>\n",
       "      <td>91/93</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[4,2,2],[4,4,0],[6,2,...</td>\n",
       "      <td>[[2,2,1],[3,4,0],[-2,-3,0]],[[2,2,1],[-2,-3,0]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20349</th>\n",
       "      <td>[[10,0,0],[0,2,0],[0,14,34]]</td>\n",
       "      <td>22/23</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,2,2],[0,2,4],[0,4,6],[0,4,...</td>\n",
       "      <td>[[0,-1,-3],[0,2,5],[1,0,0]],[[0,2,5],[0,-1,-3]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20353</th>\n",
       "      <td>[[4,0,0],[14,26,0],[2,0,6]]</td>\n",
       "      <td>127/134</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,2,...</td>\n",
       "      <td>[[0,0,1],[0,-1,0],[1,2,0]],[[0,0,1],[1,2,0],[0...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20356</th>\n",
       "      <td>[[16,0,0],[0,10,0],[2,2,6]]</td>\n",
       "      <td>212/217</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,4,0],[0,6,0],[0,8,0],[0,10...</td>\n",
       "      <td>[[0,0,1],[1,0,0],[0,1,0]],[[0,-1,1],[1,0,0],[0...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20359</th>\n",
       "      <td>[[2,0,0],[28,46,0],[2,0,6]]</td>\n",
       "      <td>114/119</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,2,...</td>\n",
       "      <td>[[-1,-2,1],[-1,-2,0],[3,5,0]],[[-1,-2,1],[3,5,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20360</th>\n",
       "      <td>[[4,0,0],[10,26,0],[4,0,12]]</td>\n",
       "      <td>61/63</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,2,...</td>\n",
       "      <td>[[0,-1,1],[0,-1,0],[1,3,0]],[[0,-1,1],[1,3,0],...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20364</th>\n",
       "      <td>[[2,0,0],[2,4,0],[14,92,98]]</td>\n",
       "      <td>123/136</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,-1,-1],[2,14,15],[-1,-8,-9]],[[0,-1,-1],[-...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20365</th>\n",
       "      <td>[[6,0,0],[0,4,0],[8,6,14]]</td>\n",
       "      <td>56/65</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...</td>\n",
       "      <td>[[1,0,1],[0,1,1],[0,0,-1]],[[1,0,1],[0,0,-1],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20368</th>\n",
       "      <td>[[2,0,0],[2,8,0],[14,54,82]]</td>\n",
       "      <td>88/111</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,-1,-1],[1,4,6],[0,0,-1]],[[0,0,-1],[0,-1,-...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20374</th>\n",
       "      <td>[[2,0,0],[10,28,0],[0,2,6]]</td>\n",
       "      <td>61/72</td>\n",
       "      <td>[[0,0,0],[0,2,6],[2,0,0],[2,2,0],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,1,1],[1,3,0],[0,-1,0]],[[0,2,1],[1,3,0],[0...</td>\n",
       "      <td>30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20375</th>\n",
       "      <td>[[2,0,0],[22,36,0],[2,2,8]]</td>\n",
       "      <td>53/57</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...</td>\n",
       "      <td>[[0,0,1],[-1,-2,0],[3,5,0]],[[0,0,1],[3,5,0],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20376</th>\n",
       "      <td>[[4,0,0],[0,2,0],[8,2,16]]</td>\n",
       "      <td>19/27</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,4],[4,0,0],[4,2,...</td>\n",
       "      <td>[[0,0,-1],[1,0,2],[0,1,0]],[[1,0,2],[0,0,-1],[...</td>\n",
       "      <td>93</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20377</th>\n",
       "      <td>[[4,0,0],[10,24,0],[2,2,6]]</td>\n",
       "      <td>109/122</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...</td>\n",
       "      <td>[[0,0,1],[1,3,0],[0,-1,0]],[[0,0,1],[0,-1,0],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20378</th>\n",
       "      <td>[[8,0,0],[2,6,0],[0,6,10]]</td>\n",
       "      <td>82/93</td>\n",
       "      <td>[[0,0,0],[0,6,10],[2,0,0],[2,2,0],[2,2,2],[2,4...</td>\n",
       "      <td>[[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20387</th>\n",
       "      <td>[[4,0,0],[0,2,0],[146,12,218]]</td>\n",
       "      <td>115/142</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[4,0,0],[6,2,8],[10,2...</td>\n",
       "      <td>[[1,0,1],[12,1,18],[-2,0,-3]],[[-2,0,-3],[1,0,...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20389</th>\n",
       "      <td>[[8,0,0],[2,4,0],[4,16,20]]</td>\n",
       "      <td>132/133</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,-1,-2],[1,1,2],[0,1,1]],[[0,1,1],[1,1,2],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20393</th>\n",
       "      <td>[[4,0,0],[0,2,0],[136,82,204]]</td>\n",
       "      <td>283/299</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...</td>\n",
       "      <td>[[-3,-2,-5],[10,6,15],[-2,-1,-3]],[[-3,-2,-5],...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20394</th>\n",
       "      <td>[[14,0,0],[0,2,0],[2,4,6]]</td>\n",
       "      <td>4/7</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,4,6],[4,0,0],[6,0,...</td>\n",
       "      <td>[[0,0,1],[1,0,0],[0,1,0]],[[1,0,0],[0,0,1],[0,...</td>\n",
       "      <td>216</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20398</th>\n",
       "      <td>[[4,0,0],[0,2,0],[54,10,104]]</td>\n",
       "      <td>97/134</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[4,0,0],[4,2,6],[6,2,...</td>\n",
       "      <td>[[1,0,1],[5,1,10],[-1,0,-2]],[[5,1,10],[-1,0,-...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20400</th>\n",
       "      <td>[[4,0,0],[8,18,0],[2,4,8]]</td>\n",
       "      <td>38/39</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,4,...</td>\n",
       "      <td>[[0,0,1],[1,3,0],[0,-1,0]],[[0,0,1],[0,-1,0],[...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20401</th>\n",
       "      <td>[[10,0,0],[0,2,0],[4,10,24]]</td>\n",
       "      <td>10/11</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,2,4],[2,4,...</td>\n",
       "      <td>[[1,1,3],[-1,0,-1],[1,0,0]],[[-1,0,-1],[1,1,3]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20403</th>\n",
       "      <td>[[8,0,0],[2,10,0],[0,0,6]]</td>\n",
       "      <td>108/113</td>\n",
       "      <td>[[0,0,0],[0,0,2],[0,0,4],[0,0,6],[2,0,0],[2,0,...</td>\n",
       "      <td>[[0,1,0],[1,0,0],[0,0,1]],[[0,1,0],[1,0,-1],[0...</td>\n",
       "      <td>48</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20408</th>\n",
       "      <td>[[8,0,0],[2,4,0],[6,12,18]]</td>\n",
       "      <td>59/62</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...</td>\n",
       "      <td>[[0,-1,-2],[1,1,2],[0,1,1]],[[0,-1,-2],[0,1,1]...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20415</th>\n",
       "      <td>[[2,0,0],[24,38,0],[4,2,6]]</td>\n",
       "      <td>83/93</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[4,2,6],[4,4,0],[4,4,...</td>\n",
       "      <td>[[3,5,0],[-1,-2,0],[1,1,1]],[[1,1,1],[3,5,0],[...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20420</th>\n",
       "      <td>[[10,0,0],[0,8,0],[2,2,10]]</td>\n",
       "      <td>78/79</td>\n",
       "      <td>[[0,0,0],[0,2,0],[0,4,0],[0,6,0],[0,8,0],[2,0,...</td>\n",
       "      <td>[[0,0,1],[1,0,0],[0,1,0]],[[1,0,0],[0,0,1],[0,...</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20421</th>\n",
       "      <td>[[14,0,0],[0,2,0],[20,22,32]]</td>\n",
       "      <td>171/175</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...</td>\n",
       "      <td>[[-2,-1,-2],[2,2,3],[1,0,0]],[[2,2,3],[-2,-1,-...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20423</th>\n",
       "      <td>[[2,0,0],[0,2,0],[164,50,206]]</td>\n",
       "      <td>145/148</td>\n",
       "      <td>[[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,2,4],[6,2,...</td>\n",
       "      <td>[[23,7,29],[-3,-1,-4],[-4,-1,-5]],[[-3,-1,-4],...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20425</th>\n",
       "      <td>[[2,0,0],[18,44,0],[4,0,10]]</td>\n",
       "      <td>27/34</td>\n",
       "      <td>[[0,0,0],[2,0,0],[2,2,0],[2,4,0],[4,0,10],[4,6...</td>\n",
       "      <td>[[0,-1,1],[-1,-3,0],[2,5,0]],[[-1,-3,0],[2,5,0...</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>8343 rows × 5 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                  hnf  h_ratio  \\\n",
       "3        [[6,0,0],[0,2,0],[14,24,38]]      5/6   \n",
       "4         [[6,0,0],[2,6,0],[12,2,14]]    60/89   \n",
       "7         [[2,0,0],[18,22,0],[4,6,8]]    26/35   \n",
       "10       [[6,0,0],[0,2,0],[10,34,56]]   88/113   \n",
       "12        [[2,0,0],[14,18,0],[2,0,8]]    67/70   \n",
       "13        [[4,0,0],[2,6,0],[14,2,16]]    72/77   \n",
       "15        [[4,0,0],[0,2,0],[56,6,80]]   93/113   \n",
       "16         [[4,0,0],[6,16,0],[2,4,6]]    25/27   \n",
       "17       [[2,0,0],[2,8,0],[32,30,48]]  117/137   \n",
       "18          [[4,0,0],[4,6,0],[0,2,8]]    39/43   \n",
       "19       [[14,0,0],[0,4,0],[8,10,18]]  161/187   \n",
       "20     [[2,0,0],[0,2,0],[212,64,266]]  155/178   \n",
       "24         [[8,0,0],[2,6,0],[4,2,10]]    83/99   \n",
       "27         [[10,0,0],[2,8,0],[4,4,6]]  106/111   \n",
       "29        [[2,0,0],[2,4,0],[30,8,44]]    31/33   \n",
       "31       [[6,0,0],[0,2,0],[12,14,54]]    35/54   \n",
       "35       [[2,0,0],[12,14,0],[8,6,12]]    11/17   \n",
       "38       [[4,0,0],[0,4,0],[50,12,74]]  139/196   \n",
       "41       [[2,0,0],[2,4,0],[72,56,82]]   79/108   \n",
       "44       [[14,0,0],[0,4,0],[2,12,34]]    23/25   \n",
       "49       [[8,0,0],[0,2,0],[22,10,26]]    32/39   \n",
       "55       [[4,0,0],[2,4,0],[10,20,54]]  163/172   \n",
       "58        [[2,0,0],[22,36,0],[4,2,6]]     9/10   \n",
       "59        [[2,0,0],[26,34,0],[4,4,6]]    19/21   \n",
       "60       [[4,0,0],[0,2,0],[16,50,72]]   97/103   \n",
       "61       [[6,0,0],[0,2,0],[26,14,40]]    62/79   \n",
       "69        [[6,0,0],[2,4,0],[0,10,18]]    64/77   \n",
       "72       [[14,0,0],[4,10,0],[0,2,14]]  175/184   \n",
       "74         [[6,0,0],[4,12,0],[2,2,8]]    53/59   \n",
       "75        [[12,0,0],[4,10,0],[2,2,8]]  193/198   \n",
       "...                               ...      ...   \n",
       "20343      [[8,0,0],[4,10,0],[2,6,8]]    15/16   \n",
       "20344     [[14,0,0],[4,8,0],[2,2,12]]  245/256   \n",
       "20347    [[2,0,0],[18,22,0],[8,2,10]]    91/93   \n",
       "20349    [[10,0,0],[0,2,0],[0,14,34]]    22/23   \n",
       "20353     [[4,0,0],[14,26,0],[2,0,6]]  127/134   \n",
       "20356     [[16,0,0],[0,10,0],[2,2,6]]  212/217   \n",
       "20359     [[2,0,0],[28,46,0],[2,0,6]]  114/119   \n",
       "20360    [[4,0,0],[10,26,0],[4,0,12]]    61/63   \n",
       "20364    [[2,0,0],[2,4,0],[14,92,98]]  123/136   \n",
       "20365      [[6,0,0],[0,4,0],[8,6,14]]    56/65   \n",
       "20368    [[2,0,0],[2,8,0],[14,54,82]]   88/111   \n",
       "20374     [[2,0,0],[10,28,0],[0,2,6]]    61/72   \n",
       "20375     [[2,0,0],[22,36,0],[2,2,8]]    53/57   \n",
       "20376      [[4,0,0],[0,2,0],[8,2,16]]    19/27   \n",
       "20377     [[4,0,0],[10,24,0],[2,2,6]]  109/122   \n",
       "20378      [[8,0,0],[2,6,0],[0,6,10]]    82/93   \n",
       "20387  [[4,0,0],[0,2,0],[146,12,218]]  115/142   \n",
       "20389     [[8,0,0],[2,4,0],[4,16,20]]  132/133   \n",
       "20393  [[4,0,0],[0,2,0],[136,82,204]]  283/299   \n",
       "20394      [[14,0,0],[0,2,0],[2,4,6]]      4/7   \n",
       "20398   [[4,0,0],[0,2,0],[54,10,104]]   97/134   \n",
       "20400      [[4,0,0],[8,18,0],[2,4,8]]    38/39   \n",
       "20401    [[10,0,0],[0,2,0],[4,10,24]]    10/11   \n",
       "20403      [[8,0,0],[2,10,0],[0,0,6]]  108/113   \n",
       "20408     [[8,0,0],[2,4,0],[6,12,18]]    59/62   \n",
       "20415     [[2,0,0],[24,38,0],[4,2,6]]    83/93   \n",
       "20420     [[10,0,0],[0,8,0],[2,2,10]]    78/79   \n",
       "20421   [[14,0,0],[0,2,0],[20,22,32]]  171/175   \n",
       "20423  [[2,0,0],[0,2,0],[164,50,206]]  145/148   \n",
       "20425    [[2,0,0],[18,44,0],[4,0,10]]    27/34   \n",
       "\n",
       "                                                     mms  \\\n",
       "3      [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,4,4],[4,0,...   \n",
       "4      [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...   \n",
       "7      [[0,0,0],[2,0,0],[2,2,0],[4,4,0],[4,6,8],[6,6,...   \n",
       "10     [[0,0,0],[0,2,0],[2,0,0],[2,4,6],[2,6,8],[4,0,...   \n",
       "12     [[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,0,...   \n",
       "13     [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...   \n",
       "15     [[0,0,0],[0,2,0],[2,0,0],[4,0,0],[6,2,8],[8,2,...   \n",
       "16     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...   \n",
       "17     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,6,...   \n",
       "18     [[0,0,0],[0,2,8],[2,0,0],[2,2,0],[2,2,2],[2,2,...   \n",
       "19     [[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...   \n",
       "20     [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,2,4],[6,2,...   \n",
       "24     [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[2,6,0],[4,0,...   \n",
       "27     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,6,...   \n",
       "29     [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[4,2,4],[6,2,...   \n",
       "31     [[0,0,0],[0,2,0],[2,0,0],[2,2,6],[4,0,0],[4,2,...   \n",
       "35     [[0,0,0],[2,0,0],[4,2,4],[4,4,2],[6,4,8],[6,6,...   \n",
       "38     [[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...   \n",
       "41     [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[10,8,10],[12...   \n",
       "44     [[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...   \n",
       "49     [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...   \n",
       "55     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,4,...   \n",
       "58     [[0,0,0],[2,0,0],[2,2,0],[4,2,6],[4,4,0],[4,6,...   \n",
       "59     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[4,4,0],[4,4,...   \n",
       "60     [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,4,4],[2,6,...   \n",
       "61     [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...   \n",
       "69     [[0,0,0],[0,10,18],[2,0,0],[2,2,0],[2,2,2],[2,...   \n",
       "72     [[0,0,0],[0,2,14],[2,0,0],[2,2,0],[2,2,2],[2,2...   \n",
       "74     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...   \n",
       "75     [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...   \n",
       "...                                                  ...   \n",
       "20343  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...   \n",
       "20344  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...   \n",
       "20347  [[0,0,0],[2,0,0],[2,2,0],[4,2,2],[4,4,0],[6,2,...   \n",
       "20349  [[0,0,0],[0,2,0],[0,2,2],[0,2,4],[0,4,6],[0,4,...   \n",
       "20353  [[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,2,...   \n",
       "20356  [[0,0,0],[0,2,0],[0,4,0],[0,6,0],[0,8,0],[0,10...   \n",
       "20359  [[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,2,...   \n",
       "20360  [[0,0,0],[2,0,0],[2,0,2],[2,0,4],[2,0,6],[2,2,...   \n",
       "20364  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...   \n",
       "20365  [[0,0,0],[0,2,0],[0,4,0],[2,0,0],[2,2,0],[2,2,...   \n",
       "20368  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...   \n",
       "20374  [[0,0,0],[0,2,6],[2,0,0],[2,2,0],[2,4,0],[2,4,...   \n",
       "20375  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...   \n",
       "20376  [[0,0,0],[0,2,0],[2,0,0],[2,2,4],[4,0,0],[4,2,...   \n",
       "20377  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,2,...   \n",
       "20378  [[0,0,0],[0,6,10],[2,0,0],[2,2,0],[2,2,2],[2,4...   \n",
       "20387  [[0,0,0],[0,2,0],[2,0,0],[4,0,0],[6,2,8],[10,2...   \n",
       "20389  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...   \n",
       "20393  [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...   \n",
       "20394  [[0,0,0],[0,2,0],[2,0,0],[2,4,6],[4,0,0],[6,0,...   \n",
       "20398  [[0,0,0],[0,2,0],[2,0,0],[4,0,0],[4,2,6],[6,2,...   \n",
       "20400  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,2,4],[2,4,...   \n",
       "20401  [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[2,2,4],[2,4,...   \n",
       "20403  [[0,0,0],[0,0,2],[0,0,4],[0,0,6],[2,0,0],[2,0,...   \n",
       "20408  [[0,0,0],[2,0,0],[2,2,0],[2,2,2],[2,4,0],[2,4,...   \n",
       "20415  [[0,0,0],[2,0,0],[2,2,0],[4,2,6],[4,4,0],[4,4,...   \n",
       "20420  [[0,0,0],[0,2,0],[0,4,0],[0,6,0],[0,8,0],[2,0,...   \n",
       "20421  [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,0,0],[4,2,...   \n",
       "20423  [[0,0,0],[0,2,0],[2,0,0],[2,2,2],[4,2,4],[6,2,...   \n",
       "20425  [[0,0,0],[2,0,0],[2,2,0],[2,4,0],[4,0,10],[4,6...   \n",
       "\n",
       "                                              companions  n_companions  \n",
       "3      [[2,3,5],[-1,-1,-2],[1,0,0]],[[-1,-1,-2],[2,3,...             6  \n",
       "4      [[1,0,1],[-1,1,0],[1,0,0]],[[-1,1,0],[1,0,1],[...            12  \n",
       "7      [[2,3,1],[3,4,0],[-2,-3,0]],[[3,4,0],[-2,-3,0]...             6  \n",
       "10     [[0,-3,-5],[0,2,3],[1,3,5]],[[0,2,3],[0,-3,-5]...             6  \n",
       "12     [[-2,-3,1],[-2,-3,0],[3,4,0]],[[-2,-3,1],[3,4,...             6  \n",
       "13     [[-2,0,-3],[3,1,4],[1,0,1]],[[0,0,-1],[0,1,1],...            12  \n",
       "15     [[1,0,1],[8,1,12],[-2,0,-3]],[[8,1,12],[-2,0,-...             6  \n",
       "16     [[0,0,1],[0,-1,0],[1,3,0]],[[-1,-3,1],[0,-1,0]...            18  \n",
       "17     [[-3,-2,-5],[2,1,3],[2,2,3]],[[2,1,3],[-3,-2,-...             6  \n",
       "18     [[0,0,1],[0,1,0],[1,0,0]],[[0,0,1],[-1,1,0],[1...            84  \n",
       "19     [[-1,0,-1],[1,1,2],[1,0,0]],[[1,1,2],[-1,0,-1]...             6  \n",
       "20     [[-4,-1,-5],[-3,-1,-4],[23,7,29]],[[-4,-1,-5],...             6  \n",
       "24     [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "27     [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "29     [[4,1,6],[-3,0,-5],[2,0,3]],[[4,1,6],[2,0,3],[...             6  \n",
       "31     [[1,1,4],[-1,0,-1],[1,0,0]],[[-1,0,-1],[1,1,4]...            12  \n",
       "35     [[3,4,0],[-2,-3,0],[1,1,1]],[[1,1,1],[3,4,0],[...             6  \n",
       "38     [[-2,0,-3],[1,0,1],[4,1,6]],[[1,0,1],[4,1,6],[...             6  \n",
       "41     [[13,10,15],[-5,-4,-6],[1,1,1]],[[1,1,1],[13,1...             6  \n",
       "44     [[0,0,-1],[0,1,3],[1,0,0]],[[0,1,3],[0,0,-1],[...             6  \n",
       "49     [[3,1,3],[-2,0,-1],[1,0,0]],[[-2,0,-1],[3,1,3]...            18  \n",
       "55     [[0,-1,-3],[1,2,6],[0,0,-1]],[[0,0,-1],[1,2,6]...             6  \n",
       "58     [[3,5,0],[-1,-2,0],[1,1,1]],[[1,1,1],[-1,-2,0]...            18  \n",
       "59     [[0,0,1],[-2,-3,0],[3,4,0]],[[0,0,1],[3,4,0],[...             6  \n",
       "60     [[1,5,7],[-1,-4,-6],[1,2,3]],[[-1,-4,-6],[1,5,...             6  \n",
       "61     [[2,1,3],[-1,0,-1],[1,0,0]],[[-1,0,-1],[2,1,3]...            18  \n",
       "69     [[0,0,-1],[0,1,2],[1,0,0]],[[0,1,2],[0,0,-1],[...            18  \n",
       "72     [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "74     [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "75     [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "...                                                  ...           ...  \n",
       "20343  [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "20344  [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...             6  \n",
       "20347  [[2,2,1],[3,4,0],[-2,-3,0]],[[2,2,1],[-2,-3,0]...             6  \n",
       "20349  [[0,-1,-3],[0,2,5],[1,0,0]],[[0,2,5],[0,-1,-3]...             6  \n",
       "20353  [[0,0,1],[0,-1,0],[1,2,0]],[[0,0,1],[1,2,0],[0...             6  \n",
       "20356  [[0,0,1],[1,0,0],[0,1,0]],[[0,-1,1],[1,0,0],[0...            18  \n",
       "20359  [[-1,-2,1],[-1,-2,0],[3,5,0]],[[-1,-2,1],[3,5,...             6  \n",
       "20360  [[0,-1,1],[0,-1,0],[1,3,0]],[[0,-1,1],[1,3,0],...             6  \n",
       "20364  [[0,-1,-1],[2,14,15],[-1,-8,-9]],[[0,-1,-1],[-...             6  \n",
       "20365  [[1,0,1],[0,1,1],[0,0,-1]],[[1,0,1],[0,0,-1],[...             6  \n",
       "20368  [[0,-1,-1],[1,4,6],[0,0,-1]],[[0,0,-1],[0,-1,-...             6  \n",
       "20374  [[0,1,1],[1,3,0],[0,-1,0]],[[0,2,1],[1,3,0],[0...            30  \n",
       "20375  [[0,0,1],[-1,-2,0],[3,5,0]],[[0,0,1],[3,5,0],[...             6  \n",
       "20376  [[0,0,-1],[1,0,2],[0,1,0]],[[1,0,2],[0,0,-1],[...            93  \n",
       "20377  [[0,0,1],[1,3,0],[0,-1,0]],[[0,0,1],[0,-1,0],[...             6  \n",
       "20378  [[0,0,1],[0,1,0],[1,0,0]],[[0,1,0],[0,0,1],[1,...            18  \n",
       "20387  [[1,0,1],[12,1,18],[-2,0,-3]],[[-2,0,-3],[1,0,...             6  \n",
       "20389  [[0,-1,-2],[1,1,2],[0,1,1]],[[0,1,1],[1,1,2],[...             6  \n",
       "20393  [[-3,-2,-5],[10,6,15],[-2,-1,-3]],[[-3,-2,-5],...             6  \n",
       "20394  [[0,0,1],[1,0,0],[0,1,0]],[[1,0,0],[0,0,1],[0,...           216  \n",
       "20398  [[1,0,1],[5,1,10],[-1,0,-2]],[[5,1,10],[-1,0,-...             6  \n",
       "20400  [[0,0,1],[1,3,0],[0,-1,0]],[[0,0,1],[0,-1,0],[...             6  \n",
       "20401  [[1,1,3],[-1,0,-1],[1,0,0]],[[-1,0,-1],[1,1,3]...             6  \n",
       "20403  [[0,1,0],[1,0,0],[0,0,1]],[[0,1,0],[1,0,-1],[0...            48  \n",
       "20408  [[0,-1,-2],[1,1,2],[0,1,1]],[[0,-1,-2],[0,1,1]...             6  \n",
       "20415  [[3,5,0],[-1,-2,0],[1,1,1]],[[1,1,1],[3,5,0],[...            18  \n",
       "20420  [[0,0,1],[1,0,0],[0,1,0]],[[1,0,0],[0,0,1],[0,...            18  \n",
       "20421  [[-2,-1,-2],[2,2,3],[1,0,0]],[[2,2,3],[-2,-1,-...             6  \n",
       "20423  [[23,7,29],[-3,-1,-4],[-4,-1,-5]],[[-3,-1,-4],...             6  \n",
       "20425  [[0,-1,1],[-1,-3,0],[2,5,0]],[[-1,-3,0],[2,5,0...             6  \n",
       "\n",
       "[8343 rows x 5 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.query('h_ratio > 1/2 and h_ratio < 1')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or one can ask for the vector of $h$-ratio counts of Hermite Normal Forms. The first column refers to the **$h$-ratios**, the second column refers the count of lattices with the corresponding **$h$-ratio**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0          3098\n",
      "2/95          1\n",
      "2/93          1\n",
      "1/43          1\n",
      "1/42          2\n",
      "2/83          1\n",
      "4/165         1\n",
      "1/41          2\n",
      "2/81          1\n",
      "1/40          2\n",
      "2/79          1\n",
      "1/39          5\n",
      "2/77          3\n",
      "1/38          4\n",
      "4/151         2\n",
      "2/75          1\n",
      "4/149         1\n",
      "1/37          4\n",
      "2/73          2\n",
      "1/36          1\n",
      "2/71          4\n",
      "1/35          7\n",
      "2/69          5\n",
      "1/34          5\n",
      "4/135         2\n",
      "2/67          6\n",
      "4/133         1\n",
      "1/33          8\n",
      "4/131         1\n",
      "2/65          4\n",
      "           ... \n",
      "226/227       1\n",
      "228/229       2\n",
      "231/232       1\n",
      "235/236       1\n",
      "471/473       2\n",
      "239/240       1\n",
      "240/241       1\n",
      "242/243       1\n",
      "244/245       3\n",
      "251/252       1\n",
      "252/253       2\n",
      "253/254       1\n",
      "254/255       2\n",
      "509/511       2\n",
      "258/259       1\n",
      "260/261       1\n",
      "267/268       1\n",
      "268/269       2\n",
      "278/279       2\n",
      "280/281       2\n",
      "281/282       1\n",
      "282/283       2\n",
      "292/293       2\n",
      "309/310       1\n",
      "319/320       1\n",
      "347/348       1\n",
      "348/349       2\n",
      "357/358       1\n",
      "396/397       2\n",
      "1          3662\n",
      "Name: h_ratio, Length: 3644, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "h = df[\"h_ratio\"].value_counts().sort_index()\n",
    "print(h)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We define two auxiliary functions to have a human readable version of the **$h$-ratio** statistics."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def stats(h_counts):\n",
    "    values = h_counts.keys().map(abs) # set -1 ratios to 1\n",
    "    counts = h_counts.values\n",
    "    d = DescrStatsW(values, weights=counts)\n",
    "    q = d.quantile([0.25,0.5,0.75])\n",
    "    \n",
    "    s = {'count':sum(counts), 'mean':d.mean, 'std':d.std, 'min':min(values),\n",
    "         '25%':q[0.25], '50%':q[0.5], '75%':q[0.75], 'max':max(values)}\n",
    "\n",
    "    return s\n",
    "\n",
    "def print_stats(h_counts):\n",
    "    s = stats(h_counts)\n",
    "    for v in stats(h_counts):\n",
    "        print(v,\":\",s[v])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count : 20429\n",
      "mean : 0.5833574869155574\n",
      "std : 0.41288860321950976\n",
      "min : 0\n",
      "25% : 2/19\n",
      "50% : 38/47\n",
      "75% : 101/104\n",
      "max : 1\n"
     ]
    }
   ],
   "source": [
    "print_stats(h)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Database Statistics"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The method given above for navigation of the database is not feasible for bigger chunks of the database ( such as dim bla deg bla) since this method loads everything on the chosen .db.csv.gz file to the RAM. \n",
    "However, one can directly access to the statistics of the chosen database without loading the whole database using the <span style=\"color:blue\">MMS_dim***n***_deg***2d***.db.hist</span>.\n",
    "\n",
    "In order to read the data in .db.hist, we first define the auxiliary function <span style=\"color:blue\">read_hist</span> as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_hist(filename):\n",
    "    f = open(\"hist/\"+filename,\"r\")\n",
    "\n",
    "    # create two dicts, one for hnfs one for companion counts\n",
    "    hnfs = {}\n",
    "    for s in f.readline().split(\")(\"):\n",
    "        es = s.split(\":\")\n",
    "        key = abs(Fraction(es[0].strip(\"()\")))\n",
    "        if(key == 1): # both 1 and -1 ratios count to 1\n",
    "            hnfs[key] = hnfs.get(key,0) + int(es[1].strip(\"()\\n\"))\n",
    "        else:\n",
    "            hnfs[key] = int(es[1].strip(\"()\\n\"))\n",
    "    hnfs = pd.Series(hnfs)\n",
    "\n",
    "\n",
    "    comps = {}\n",
    "    for s in f.readline().split(\")(\"):\n",
    "        es = s.split(\":\")\n",
    "        key = abs(Fraction(es[0].strip(\"()\")))\n",
    "        if(key == 1):\n",
    "            comps[key] = comps.get(key,0) + int(es[1].strip(\"()\\n\"))\n",
    "        else:\n",
    "            comps[key] = int(es[1].strip(\"()\\n\"))\n",
    "    comps = pd.Series(comps)\n",
    "    \n",
    "    return (hnfs,comps)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we load the data using the function <span style=\"color:blue\">read_hist</span>. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "histfile = 'MMS_dim3_deg16.db.hist'\n",
    "histdata = read_hist(histfile)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The function <span style=\"color:blue\">read_hist</span> returns a pair. The first component of the *histdata* corresponds to the **h-ratio** statistics after the Hermite Normal Form reduction. The second component corresponds to the **h-ratio** statistics without the reduction. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20/129     1\n",
       "88/111     1\n",
       "260/267    1\n",
       "359/375    1\n",
       "183/239    1\n",
       "346/357    1\n",
       "58/89      1\n",
       "16/107     1\n",
       "69/103     1\n",
       "209/217    1\n",
       "128/163    1\n",
       "257/261    1\n",
       "167/174    1\n",
       "137/164    1\n",
       "201/229    1\n",
       "83/108     1\n",
       "145/182    1\n",
       "115/149    1\n",
       "110/149    1\n",
       "75/86      1\n",
       "235/236    1\n",
       "229/268    1\n",
       "109/157    1\n",
       "105/202    1\n",
       "136/145    1\n",
       "115/154    1\n",
       "46/59      1\n",
       "174/193    1\n",
       "4/131      1\n",
       "75/166     1\n",
       "          ..\n",
       "105/139    1\n",
       "160/169    1\n",
       "157/211    1\n",
       "201/203    1\n",
       "149/157    1\n",
       "189/199    2\n",
       "77/111     1\n",
       "61/73      2\n",
       "23/93      3\n",
       "149/179    1\n",
       "157/163    1\n",
       "140/143    2\n",
       "125/142    1\n",
       "35/52      2\n",
       "129/136    1\n",
       "131/176    1\n",
       "152/169    2\n",
       "107/142    1\n",
       "97/132     1\n",
       "201/206    2\n",
       "77/124     1\n",
       "487/507    2\n",
       "113/126    2\n",
       "65/74      1\n",
       "103/113    1\n",
       "143/146    1\n",
       "184/209    1\n",
       "23/67      7\n",
       "239/249    1\n",
       "149/188    1\n",
       "Length: 3644, dtype: int64"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "histdata[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20/129       6\n",
       "88/111       6\n",
       "260/267      6\n",
       "359/375      6\n",
       "183/239      6\n",
       "346/357      6\n",
       "58/89       18\n",
       "16/107       6\n",
       "69/103       6\n",
       "209/217      6\n",
       "128/163      6\n",
       "257/261      6\n",
       "167/174      6\n",
       "137/164      6\n",
       "201/229      6\n",
       "83/108       6\n",
       "145/182      6\n",
       "115/149      6\n",
       "110/149      6\n",
       "75/86        6\n",
       "235/236      6\n",
       "229/268      6\n",
       "109/157      6\n",
       "105/202      6\n",
       "136/145      6\n",
       "115/154      6\n",
       "46/59        3\n",
       "174/193      6\n",
       "4/131        6\n",
       "75/166       6\n",
       "          ... \n",
       "105/139      6\n",
       "160/169      6\n",
       "157/211      6\n",
       "201/203      6\n",
       "149/157      6\n",
       "189/199     12\n",
       "77/111       6\n",
       "61/73       48\n",
       "23/93       18\n",
       "149/179      6\n",
       "157/163      6\n",
       "140/143     12\n",
       "125/142      6\n",
       "35/52       12\n",
       "129/136      6\n",
       "131/176      6\n",
       "152/169     12\n",
       "107/142      6\n",
       "97/132       6\n",
       "201/206     24\n",
       "77/124       6\n",
       "487/507     12\n",
       "113/126     12\n",
       "65/74        6\n",
       "103/113      6\n",
       "143/146      6\n",
       "184/209      6\n",
       "23/67      102\n",
       "239/249      6\n",
       "149/188      6\n",
       "Length: 3644, dtype: int64"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "histdata[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can see the **$h$-ratio** statistics using the <span style=\"color:blue\">print_stats</span> function we defined earlier."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count : 20429\n",
      "mean : 0.5833574869155577\n",
      "std : 0.41288860321950926\n",
      "min : 0\n",
      "25% : 2/19\n",
      "50% : 38/47\n",
      "75% : 101/104\n",
      "max : 1\n"
     ]
    }
   ],
   "source": [
    "print_stats(histdata[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count : 659082\n",
      "mean : 0.6388275840227783\n",
      "std : 0.41231605366290613\n",
      "min : 0\n",
      "25% : 1/5\n",
      "50% : 215/233\n",
      "75% : 1\n",
      "max : 1\n"
     ]
    }
   ],
   "source": [
    "print_stats(histdata[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One can print the statistics of all files in the database using the following code. In each row we have the following information:\n",
    "* **25%-50%-75%** indicates the 25th, 50th 75th percentiles of the $h$-ratio distribution. \n",
    "* **companion** indicates whether the dataset corresponds to Hermite Normal Forms or simplicial sets( i.e. if **companion** is true dataset belongs to the simplicial sets and otherwise dataset belongs to Hermite Normal Forms that arise from the simplicial sets.\n",
    "* **count** indicates the number of simplicial sets or lattices. \n",
    "* **deg** indicates the maximum 1-norm of the allowed simplicial sets in the dataset.\n",
    "* **dim** indicates the dimension of the dataset.\n",
    "* **max** indicates the maximum value of $h$-ratio in the dataset.\n",
    "* **mean** indicates the mean value of $h$-ratio in the dataset.\n",
    "* **max** indicates the minimum value of $h$-ratio in the dataset.\n",
    "* **rnd** indicates whether the dataset is sampled or not. More specifically if this is False, then the dataset contains all possible instances of the given deg and dim. If this is True, it means that this is a sampled dataset.\n",
    "* **std** indicates the standart deviation of the $h$-ratio in the dataset.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>companion</th>\n",
       "      <th>count</th>\n",
       "      <th>deg</th>\n",
       "      <th>dim</th>\n",
       "      <th>filename</th>\n",
       "      <th>max</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>rnd</th>\n",
       "      <th>std</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2/19</td>\n",
       "      <td>38/47</td>\n",
       "      <td>101/104</td>\n",
       "      <td>False</td>\n",
       "      <td>20429</td>\n",
       "      <td>16</td>\n",
       "      <td>3</td>\n",
       "      <td>MMS_dim3_deg16.db.hist</td>\n",
       "      <td>1</td>\n",
       "      <td>0.583357</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>0.412889</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1/5</td>\n",
       "      <td>215/233</td>\n",
       "      <td>1</td>\n",
       "      <td>True</td>\n",
       "      <td>659082</td>\n",
       "      <td>16</td>\n",
       "      <td>3</td>\n",
       "      <td>MMS_dim3_deg16.db.hist</td>\n",
       "      <td>1</td>\n",
       "      <td>0.638828</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>0.412316</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    25%      50%      75%  companion   count  deg  dim  \\\n",
       "0  2/19    38/47  101/104      False   20429   16    3   \n",
       "1   1/5  215/233        1       True  659082   16    3   \n",
       "\n",
       "                 filename max      mean min    rnd       std  \n",
       "0  MMS_dim3_deg16.db.hist   1  0.583357   0  False  0.412889  \n",
       "1  MMS_dim3_deg16.db.hist   1  0.638828   0  False  0.412316  "
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l=[]\n",
    "for f in os.listdir('hist/'):            \n",
    "    c = False\n",
    "    for d in read_hist(f):\n",
    "        s = stats(d)\n",
    "        s['companion'] = c\n",
    "        s['rnd'] = \"rnd\" in f\n",
    "        s['dim'] = int(re.search('dim([0-9]+)_',f).group(1))\n",
    "        s['deg'] = int(re.search('deg([0-9]+)',f).group(1))\n",
    "        s['hist_data'] = d\n",
    "        s['filename'] = f\n",
    "        c = True\n",
    "        l.append(s)\n",
    "sdf=pd.DataFrame(l).sort_values(['dim','deg','companion'], ascending=[True, True, True])\n",
    "sdf.drop('hist_data', axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One can also visualize the distribution of the $h$-ratio using the package *matplotlib*. The following code allows us to see distribution of $h$-ratio both over the simplical sets (red) and over the Herminte Normal Forms (blue)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "/* Put everything inside the global mpl namespace */\n",
       "window.mpl = {};\n",
       "\n",
       "\n",
       "mpl.get_websocket_type = function() {\n",
       "    if (typeof(WebSocket) !== 'undefined') {\n",
       "        return WebSocket;\n",
       "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
       "        return MozWebSocket;\n",
       "    } else {\n",
       "        alert('Your browser does not have WebSocket support. ' +\n",
       "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
       "              'Firefox 4 and 5 are also supported but you ' +\n",
       "              'have to enable WebSockets in about:config.');\n",
       "    };\n",
       "}\n",
       "\n",
       "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
       "    this.id = figure_id;\n",
       "\n",
       "    this.ws = websocket;\n",
       "\n",
       "    this.supports_binary = (this.ws.binaryType != undefined);\n",
       "\n",
       "    if (!this.supports_binary) {\n",
       "        var warnings = document.getElementById(\"mpl-warnings\");\n",
       "        if (warnings) {\n",
       "            warnings.style.display = 'block';\n",
       "            warnings.textContent = (\n",
       "                \"This browser does not support binary websocket messages. \" +\n",
       "                    \"Performance may be slow.\");\n",
       "        }\n",
       "    }\n",
       "\n",
       "    this.imageObj = new Image();\n",
       "\n",
       "    this.context = undefined;\n",
       "    this.message = undefined;\n",
       "    this.canvas = undefined;\n",
       "    this.rubberband_canvas = undefined;\n",
       "    this.rubberband_context = undefined;\n",
       "    this.format_dropdown = undefined;\n",
       "\n",
       "    this.image_mode = 'full';\n",
       "\n",
       "    this.root = $('<div/>');\n",
       "    this._root_extra_style(this.root)\n",
       "    this.root.attr('style', 'display: inline-block');\n",
       "\n",
       "    $(parent_element).append(this.root);\n",
       "\n",
       "    this._init_header(this);\n",
       "    this._init_canvas(this);\n",
       "    this._init_toolbar(this);\n",
       "\n",
       "    var fig = this;\n",
       "\n",
       "    this.waiting = false;\n",
       "\n",
       "    this.ws.onopen =  function () {\n",
       "            fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
       "            fig.send_message(\"send_image_mode\", {});\n",
       "            if (mpl.ratio != 1) {\n",
       "                fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
       "            }\n",
       "            fig.send_message(\"refresh\", {});\n",
       "        }\n",
       "\n",
       "    this.imageObj.onload = function() {\n",
       "            if (fig.image_mode == 'full') {\n",
       "                // Full images could contain transparency (where diff images\n",
       "                // almost always do), so we need to clear the canvas so that\n",
       "                // there is no ghosting.\n",
       "                fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
       "            }\n",
       "            fig.context.drawImage(fig.imageObj, 0, 0);\n",
       "        };\n",
       "\n",
       "    this.imageObj.onunload = function() {\n",
       "        fig.ws.close();\n",
       "    }\n",
       "\n",
       "    this.ws.onmessage = this._make_on_message_function(this);\n",
       "\n",
       "    this.ondownload = ondownload;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_header = function() {\n",
       "    var titlebar = $(\n",
       "        '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
       "        'ui-helper-clearfix\"/>');\n",
       "    var titletext = $(\n",
       "        '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
       "        'text-align: center; padding: 3px;\"/>');\n",
       "    titlebar.append(titletext)\n",
       "    this.root.append(titlebar);\n",
       "    this.header = titletext[0];\n",
       "}\n",
       "\n",
       "\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
       "\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
       "\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_canvas = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var canvas_div = $('<div/>');\n",
       "\n",
       "    canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
       "\n",
       "    function canvas_keyboard_event(event) {\n",
       "        return fig.key_event(event, event['data']);\n",
       "    }\n",
       "\n",
       "    canvas_div.keydown('key_press', canvas_keyboard_event);\n",
       "    canvas_div.keyup('key_release', canvas_keyboard_event);\n",
       "    this.canvas_div = canvas_div\n",
       "    this._canvas_extra_style(canvas_div)\n",
       "    this.root.append(canvas_div);\n",
       "\n",
       "    var canvas = $('<canvas/>');\n",
       "    canvas.addClass('mpl-canvas');\n",
       "    canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
       "\n",
       "    this.canvas = canvas[0];\n",
       "    this.context = canvas[0].getContext(\"2d\");\n",
       "\n",
       "    var backingStore = this.context.backingStorePixelRatio ||\n",
       "\tthis.context.webkitBackingStorePixelRatio ||\n",
       "\tthis.context.mozBackingStorePixelRatio ||\n",
       "\tthis.context.msBackingStorePixelRatio ||\n",
       "\tthis.context.oBackingStorePixelRatio ||\n",
       "\tthis.context.backingStorePixelRatio || 1;\n",
       "\n",
       "    mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
       "\n",
       "    var rubberband = $('<canvas/>');\n",
       "    rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
       "\n",
       "    var pass_mouse_events = true;\n",
       "\n",
       "    canvas_div.resizable({\n",
       "        start: function(event, ui) {\n",
       "            pass_mouse_events = false;\n",
       "        },\n",
       "        resize: function(event, ui) {\n",
       "            fig.request_resize(ui.size.width, ui.size.height);\n",
       "        },\n",
       "        stop: function(event, ui) {\n",
       "            pass_mouse_events = true;\n",
       "            fig.request_resize(ui.size.width, ui.size.height);\n",
       "        },\n",
       "    });\n",
       "\n",
       "    function mouse_event_fn(event) {\n",
       "        if (pass_mouse_events)\n",
       "            return fig.mouse_event(event, event['data']);\n",
       "    }\n",
       "\n",
       "    rubberband.mousedown('button_press', mouse_event_fn);\n",
       "    rubberband.mouseup('button_release', mouse_event_fn);\n",
       "    // Throttle sequential mouse events to 1 every 20ms.\n",
       "    rubberband.mousemove('motion_notify', mouse_event_fn);\n",
       "\n",
       "    rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
       "    rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
       "\n",
       "    canvas_div.on(\"wheel\", function (event) {\n",
       "        event = event.originalEvent;\n",
       "        event['data'] = 'scroll'\n",
       "        if (event.deltaY < 0) {\n",
       "            event.step = 1;\n",
       "        } else {\n",
       "            event.step = -1;\n",
       "        }\n",
       "        mouse_event_fn(event);\n",
       "    });\n",
       "\n",
       "    canvas_div.append(canvas);\n",
       "    canvas_div.append(rubberband);\n",
       "\n",
       "    this.rubberband = rubberband;\n",
       "    this.rubberband_canvas = rubberband[0];\n",
       "    this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
       "    this.rubberband_context.strokeStyle = \"#000000\";\n",
       "\n",
       "    this._resize_canvas = function(width, height) {\n",
       "        // Keep the size of the canvas, canvas container, and rubber band\n",
       "        // canvas in synch.\n",
       "        canvas_div.css('width', width)\n",
       "        canvas_div.css('height', height)\n",
       "\n",
       "        canvas.attr('width', width * mpl.ratio);\n",
       "        canvas.attr('height', height * mpl.ratio);\n",
       "        canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
       "\n",
       "        rubberband.attr('width', width);\n",
       "        rubberband.attr('height', height);\n",
       "    }\n",
       "\n",
       "    // Set the figure to an initial 600x600px, this will subsequently be updated\n",
       "    // upon first draw.\n",
       "    this._resize_canvas(600, 600);\n",
       "\n",
       "    // Disable right mouse context menu.\n",
       "    $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
       "        return false;\n",
       "    });\n",
       "\n",
       "    function set_focus () {\n",
       "        canvas.focus();\n",
       "        canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    window.setTimeout(set_focus, 100);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var nav_element = $('<div/>');\n",
       "    nav_element.attr('style', 'width: 100%');\n",
       "    this.root.append(nav_element);\n",
       "\n",
       "    // Define a callback function for later on.\n",
       "    function toolbar_event(event) {\n",
       "        return fig.toolbar_button_onclick(event['data']);\n",
       "    }\n",
       "    function toolbar_mouse_event(event) {\n",
       "        return fig.toolbar_button_onmouseover(event['data']);\n",
       "    }\n",
       "\n",
       "    for(var toolbar_ind in mpl.toolbar_items) {\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) {\n",
       "            // put a spacer in here.\n",
       "            continue;\n",
       "        }\n",
       "        var button = $('<button/>');\n",
       "        button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
       "                        'ui-button-icon-only');\n",
       "        button.attr('role', 'button');\n",
       "        button.attr('aria-disabled', 'false');\n",
       "        button.click(method_name, toolbar_event);\n",
       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
       "\n",
       "        var icon_img = $('<span/>');\n",
       "        icon_img.addClass('ui-button-icon-primary ui-icon');\n",
       "        icon_img.addClass(image);\n",
       "        icon_img.addClass('ui-corner-all');\n",
       "\n",
       "        var tooltip_span = $('<span/>');\n",
       "        tooltip_span.addClass('ui-button-text');\n",
       "        tooltip_span.html(tooltip);\n",
       "\n",
       "        button.append(icon_img);\n",
       "        button.append(tooltip_span);\n",
       "\n",
       "        nav_element.append(button);\n",
       "    }\n",
       "\n",
       "    var fmt_picker_span = $('<span/>');\n",
       "\n",
       "    var fmt_picker = $('<select/>');\n",
       "    fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
       "    fmt_picker_span.append(fmt_picker);\n",
       "    nav_element.append(fmt_picker_span);\n",
       "    this.format_dropdown = fmt_picker[0];\n",
       "\n",
       "    for (var ind in mpl.extensions) {\n",
       "        var fmt = mpl.extensions[ind];\n",
       "        var option = $(\n",
       "            '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
       "        fmt_picker.append(option);\n",
       "    }\n",
       "\n",
       "    // Add hover states to the ui-buttons\n",
       "    $( \".ui-button\" ).hover(\n",
       "        function() { $(this).addClass(\"ui-state-hover\");},\n",
       "        function() { $(this).removeClass(\"ui-state-hover\");}\n",
       "    );\n",
       "\n",
       "    var status_bar = $('<span class=\"mpl-message\"/>');\n",
       "    nav_element.append(status_bar);\n",
       "    this.message = status_bar[0];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
       "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
       "    // which will in turn request a refresh of the image.\n",
       "    this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.send_message = function(type, properties) {\n",
       "    properties['type'] = type;\n",
       "    properties['figure_id'] = this.id;\n",
       "    this.ws.send(JSON.stringify(properties));\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.send_draw_message = function() {\n",
       "    if (!this.waiting) {\n",
       "        this.waiting = true;\n",
       "        this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
       "    }\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
       "    var format_dropdown = fig.format_dropdown;\n",
       "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
       "    fig.ondownload(fig, format);\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
       "    var size = msg['size'];\n",
       "    if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
       "        fig._resize_canvas(size[0], size[1]);\n",
       "        fig.send_message(\"refresh\", {});\n",
       "    };\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
       "    var x0 = msg['x0'] / mpl.ratio;\n",
       "    var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
       "    var x1 = msg['x1'] / mpl.ratio;\n",
       "    var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
       "    x0 = Math.floor(x0) + 0.5;\n",
       "    y0 = Math.floor(y0) + 0.5;\n",
       "    x1 = Math.floor(x1) + 0.5;\n",
       "    y1 = Math.floor(y1) + 0.5;\n",
       "    var min_x = Math.min(x0, x1);\n",
       "    var min_y = Math.min(y0, y1);\n",
       "    var width = Math.abs(x1 - x0);\n",
       "    var height = Math.abs(y1 - y0);\n",
       "\n",
       "    fig.rubberband_context.clearRect(\n",
       "        0, 0, fig.canvas.width, fig.canvas.height);\n",
       "\n",
       "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
       "    // Updates the figure title.\n",
       "    fig.header.textContent = msg['label'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
       "    var cursor = msg['cursor'];\n",
       "    switch(cursor)\n",
       "    {\n",
       "    case 0:\n",
       "        cursor = 'pointer';\n",
       "        break;\n",
       "    case 1:\n",
       "        cursor = 'default';\n",
       "        break;\n",
       "    case 2:\n",
       "        cursor = 'crosshair';\n",
       "        break;\n",
       "    case 3:\n",
       "        cursor = 'move';\n",
       "        break;\n",
       "    }\n",
       "    fig.rubberband_canvas.style.cursor = cursor;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
       "    fig.message.textContent = msg['message'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
       "    // Request the server to send over a new figure.\n",
       "    fig.send_draw_message();\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
       "    fig.image_mode = msg['mode'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function() {\n",
       "    // Called whenever the canvas gets updated.\n",
       "    this.send_message(\"ack\", {});\n",
       "}\n",
       "\n",
       "// A function to construct a web socket function for onmessage handling.\n",
       "// Called in the figure constructor.\n",
       "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
       "    return function socket_on_message(evt) {\n",
       "        if (evt.data instanceof Blob) {\n",
       "            /* FIXME: We get \"Resource interpreted as Image but\n",
       "             * transferred with MIME type text/plain:\" errors on\n",
       "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
       "             * to be part of the websocket stream */\n",
       "            evt.data.type = \"image/png\";\n",
       "\n",
       "            /* Free the memory for the previous frames */\n",
       "            if (fig.imageObj.src) {\n",
       "                (window.URL || window.webkitURL).revokeObjectURL(\n",
       "                    fig.imageObj.src);\n",
       "            }\n",
       "\n",
       "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
       "                evt.data);\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "        else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
       "            fig.imageObj.src = evt.data;\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        var msg = JSON.parse(evt.data);\n",
       "        var msg_type = msg['type'];\n",
       "\n",
       "        // Call the  \"handle_{type}\" callback, which takes\n",
       "        // the figure and JSON message as its only arguments.\n",
       "        try {\n",
       "            var callback = fig[\"handle_\" + msg_type];\n",
       "        } catch (e) {\n",
       "            console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        if (callback) {\n",
       "            try {\n",
       "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
       "                callback(fig, msg);\n",
       "            } catch (e) {\n",
       "                console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
       "            }\n",
       "        }\n",
       "    };\n",
       "}\n",
       "\n",
       "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
       "mpl.findpos = function(e) {\n",
       "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
       "    var targ;\n",
       "    if (!e)\n",
       "        e = window.event;\n",
       "    if (e.target)\n",
       "        targ = e.target;\n",
       "    else if (e.srcElement)\n",
       "        targ = e.srcElement;\n",
       "    if (targ.nodeType == 3) // defeat Safari bug\n",
       "        targ = targ.parentNode;\n",
       "\n",
       "    // jQuery normalizes the pageX and pageY\n",
       "    // pageX,Y are the mouse positions relative to the document\n",
       "    // offset() returns the position of the element relative to the document\n",
       "    var x = e.pageX - $(targ).offset().left;\n",
       "    var y = e.pageY - $(targ).offset().top;\n",
       "\n",
       "    return {\"x\": x, \"y\": y};\n",
       "};\n",
       "\n",
       "/*\n",
       " * return a copy of an object with only non-object keys\n",
       " * we need this to avoid circular references\n",
       " * http://stackoverflow.com/a/24161582/3208463\n",
       " */\n",
       "function simpleKeys (original) {\n",
       "  return Object.keys(original).reduce(function (obj, key) {\n",
       "    if (typeof original[key] !== 'object')\n",
       "        obj[key] = original[key]\n",
       "    return obj;\n",
       "  }, {});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.mouse_event = function(event, name) {\n",
       "    var canvas_pos = mpl.findpos(event)\n",
       "\n",
       "    if (name === 'button_press')\n",
       "    {\n",
       "        this.canvas.focus();\n",
       "        this.canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    var x = canvas_pos.x * mpl.ratio;\n",
       "    var y = canvas_pos.y * mpl.ratio;\n",
       "\n",
       "    this.send_message(name, {x: x, y: y, button: event.button,\n",
       "                             step: event.step,\n",
       "                             guiEvent: simpleKeys(event)});\n",
       "\n",
       "    /* This prevents the web browser from automatically changing to\n",
       "     * the text insertion cursor when the button is pressed.  We want\n",
       "     * to control all of the cursor setting manually through the\n",
       "     * 'cursor' event from matplotlib */\n",
       "    event.preventDefault();\n",
       "    return false;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
       "    // Handle any extra behaviour associated with a key event\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.key_event = function(event, name) {\n",
       "\n",
       "    // Prevent repeat events\n",
       "    if (name == 'key_press')\n",
       "    {\n",
       "        if (event.which === this._key)\n",
       "            return;\n",
       "        else\n",
       "            this._key = event.which;\n",
       "    }\n",
       "    if (name == 'key_release')\n",
       "        this._key = null;\n",
       "\n",
       "    var value = '';\n",
       "    if (event.ctrlKey && event.which != 17)\n",
       "        value += \"ctrl+\";\n",
       "    if (event.altKey && event.which != 18)\n",
       "        value += \"alt+\";\n",
       "    if (event.shiftKey && event.which != 16)\n",
       "        value += \"shift+\";\n",
       "\n",
       "    value += 'k';\n",
       "    value += event.which.toString();\n",
       "\n",
       "    this._key_event_extra(event, name);\n",
       "\n",
       "    this.send_message(name, {key: value,\n",
       "                             guiEvent: simpleKeys(event)});\n",
       "    return false;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
       "    if (name == 'download') {\n",
       "        this.handle_save(this, null);\n",
       "    } else {\n",
       "        this.send_message(\"toolbar_button\", {name: name});\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
       "    this.message.textContent = tooltip;\n",
       "};\n",
       "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
       "\n",
       "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
       "\n",
       "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
       "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
       "    // object with the appropriate methods. Currently this is a non binary\n",
       "    // socket, so there is still some room for performance tuning.\n",
       "    var ws = {};\n",
       "\n",
       "    ws.close = function() {\n",
       "        comm.close()\n",
       "    };\n",
       "    ws.send = function(m) {\n",
       "        //console.log('sending', m);\n",
       "        comm.send(m);\n",
       "    };\n",
       "    // Register the callback with on_msg.\n",
       "    comm.on_msg(function(msg) {\n",
       "        //console.log('receiving', msg['content']['data'], msg);\n",
       "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
       "        ws.onmessage(msg['content']['data'])\n",
       "    });\n",
       "    return ws;\n",
       "}\n",
       "\n",
       "mpl.mpl_figure_comm = function(comm, msg) {\n",
       "    // This is the function which gets called when the mpl process\n",
       "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
       "\n",
       "    var id = msg.content.data.id;\n",
       "    // Get hold of the div created by the display call when the Comm\n",
       "    // socket was opened in Python.\n",
       "    var element = $(\"#\" + id);\n",
       "    var ws_proxy = comm_websocket_adapter(comm)\n",
       "\n",
       "    function ondownload(figure, format) {\n",
       "        window.open(figure.imageObj.src);\n",
       "    }\n",
       "\n",
       "    var fig = new mpl.figure(id, ws_proxy,\n",
       "                           ondownload,\n",
       "                           element.get(0));\n",
       "\n",
       "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
       "    // web socket which is closed, not our websocket->open comm proxy.\n",
       "    ws_proxy.onopen();\n",
       "\n",
       "    fig.parent_element = element.get(0);\n",
       "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
       "    if (!fig.cell_info) {\n",
       "        console.error(\"Failed to find cell for figure\", id, fig);\n",
       "        return;\n",
       "    }\n",
       "\n",
       "    var output_index = fig.cell_info[2]\n",
       "    var cell = fig.cell_info[0];\n",
       "\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
       "    var width = fig.canvas.width/mpl.ratio\n",
       "    fig.root.unbind('remove')\n",
       "\n",
       "    // Update the output cell to use the data from the current canvas.\n",
       "    fig.push_to_output();\n",
       "    var dataURL = fig.canvas.toDataURL();\n",
       "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
       "    // the notebook keyboard shortcuts fail.\n",
       "    IPython.keyboard_manager.enable()\n",
       "    $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
       "    fig.close_ws(fig, msg);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.close_ws = function(fig, msg){\n",
       "    fig.send_message('closing', msg);\n",
       "    // fig.ws.close()\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
       "    // Turn the data on the canvas into data in the output cell.\n",
       "    var width = this.canvas.width/mpl.ratio\n",
       "    var dataURL = this.canvas.toDataURL();\n",
       "    this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function() {\n",
       "    // Tell IPython that the notebook contents must change.\n",
       "    IPython.notebook.set_dirty(true);\n",
       "    this.send_message(\"ack\", {});\n",
       "    var fig = this;\n",
       "    // Wait a second, then push the new image to the DOM so\n",
       "    // that it is saved nicely (might be nice to debounce this).\n",
       "    setTimeout(function () { fig.push_to_output() }, 1000);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var nav_element = $('<div/>');\n",
       "    nav_element.attr('style', 'width: 100%');\n",
       "    this.root.append(nav_element);\n",
       "\n",
       "    // Define a callback function for later on.\n",
       "    function toolbar_event(event) {\n",
       "        return fig.toolbar_button_onclick(event['data']);\n",
       "    }\n",
       "    function toolbar_mouse_event(event) {\n",
       "        return fig.toolbar_button_onmouseover(event['data']);\n",
       "    }\n",
       "\n",
       "    for(var toolbar_ind in mpl.toolbar_items){\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) { continue; };\n",
       "\n",
       "        var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
       "        button.click(method_name, toolbar_event);\n",
       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
       "        nav_element.append(button);\n",
       "    }\n",
       "\n",
       "    // Add the status bar.\n",
       "    var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
       "    nav_element.append(status_bar);\n",
       "    this.message = status_bar[0];\n",
       "\n",
       "    // Add the close button to the window.\n",
       "    var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
       "    var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
       "    button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
       "    button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
       "    buttongrp.append(button);\n",
       "    var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
       "    titlebar.prepend(buttongrp);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function(el){\n",
       "    var fig = this\n",
       "    el.on(\"remove\", function(){\n",
       "\tfig.close_ws(fig, {});\n",
       "    });\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function(el){\n",
       "    // this is important to make the div 'focusable\n",
       "    el.attr('tabindex', 0)\n",
       "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
       "    // off when our div gets focus\n",
       "\n",
       "    // location in version 3\n",
       "    if (IPython.notebook.keyboard_manager) {\n",
       "        IPython.notebook.keyboard_manager.register_events(el);\n",
       "    }\n",
       "    else {\n",
       "        // location in version 2\n",
       "        IPython.keyboard_manager.register_events(el);\n",
       "    }\n",
       "\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
       "    var manager = IPython.notebook.keyboard_manager;\n",
       "    if (!manager)\n",
       "        manager = IPython.keyboard_manager;\n",
       "\n",
       "    // Check for shift+enter\n",
       "    if (event.shiftKey && event.which == 13) {\n",
       "        this.canvas_div.blur();\n",
       "        event.shiftKey = false;\n",
       "        // Send a \"J\" for go to next cell\n",
       "        event.which = 74;\n",
       "        event.keyCode = 74;\n",
       "        manager.command_mode();\n",
       "        manager.handle_keydown(event);\n",
       "    }\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
       "    fig.ondownload(fig, null);\n",
       "}\n",
       "\n",
       "\n",
       "mpl.find_output_cell = function(html_output) {\n",
       "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
       "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
       "    // IPython event is triggered only after the cells have been serialised, which for\n",
       "    // our purposes (turning an active figure into a static one), is too late.\n",
       "    var cells = IPython.notebook.get_cells();\n",
       "    var ncells = cells.length;\n",
       "    for (var i=0; i<ncells; i++) {\n",
       "        var cell = cells[i];\n",
       "        if (cell.cell_type === 'code'){\n",
       "            for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
       "                var data = cell.output_area.outputs[j];\n",
       "                if (data.data) {\n",
       "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
       "                    data = data.data;\n",
       "                }\n",
       "                if (data['text/html'] == html_output) {\n",
       "                    return [cell, data, j];\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "}\n",
       "\n",
       "// Register the function which deals with the matplotlib target/channel.\n",
       "// The kernel may be null if the page has been refreshed.\n",
       "if (IPython.notebook.kernel != null) {\n",
       "    IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
       "}\n"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<img src=\"data:image/png;base64,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8LLAZx3eeuut8vDDDw8/7927V97//vc3PcQs0O5L3iV+ID0RuXTpklRVJefPnx9uO3PmjKxZs2bFj3V//etfy7Oe9Sy5du3acNvXv/51eelLX9raeFPEZw5HWVhYkJtvvlnOnj3b9DCTxXf+HnvsMXnxi18sCwsLSM8z+Mzh/Py8VFUlhw8flttvv11mZmbkIx/5iPzvf/9re9hJ4bsOP/nJT8qHPvQhefLJJ2V+fl7uuOMO+drXvtbmkJNFuy95l/iB9ETk+gPw8uXLw23nzp2TqqpkMBgsa/vTn/5Upqenl237v//7P9m4cWMrY00Vnzm8kSeffFJe//rXywMPPNDGMJPFd/7e9a53yRe/+EUR0R+upeAzhz//+c+lqip54xvfKP/85z/lsccekzvvvFM+/vGPtz3spPBdhw8//LDccccd8qxnPUuqqpIHHnhg2Uu8ZLT7kneJH0hPRK7/183c3Nxw29mzZ1f9Sc+N27/xjW8Ub+c+c3idK1euyNve9jZ561vfKleuXGlrqEniM3/f+c535M477xxuR3qexmcOf/Ob30hVVfKDH/xguO2b3/ym3HHHHa2NN0V85vDSpUty2223yYMPPiiLi4ty8eJFue++++TDH/5w28NOEtef9PAucQPpiczMzMyyL5AdO3Zs1e/0/P73vx9u279/P7+HFfc5FHlaeO69916555575Mknn2xriEnjOn8f/ehH5dZbb5WNGzfKxo0b5ZZbbpGbbrpJXvKSl7Q53CTxuY9vuukm+eEPfzjc9s1vflM2b97cyjhTxnUOz549KzfffPOybadPn5bbb7+96SFmget3eniXuIH0RObAgQOybds2uXDhgszPz8vmzZtr/2Lhfe97n9x3333y73//Wx555BHZuHEj37gX9zlcXFyU++67T+6+++5Vf/VVGq7z9+9//1see+yxYT72sY/J2972NllYWJjAqNPC5z7+wAc+IG9605vkX//6l1y8eFFe85rXFP/rLRG/dbhu3To5evSoPPXUU3Lp0iXZsWOH3HvvvRMYdTpcvXpVBoOB7N+/X3bs2CGDwaD2J9m8S9xBeiKzuLgou3btkunpaVm/fr3s3bt3+GPHN73pTfLpT3962Pbxxx+Xd7/73fKc5zxHNm7cyL+t8Ayuc/jjH/9YqqqSm2++WW655ZZhbpzjEvFZgzfCr7f+Pz5z+J///Efe9773yW233SbPf/7z+SLzM/jM4U9+8hO58847ZXp6Wp773OfKzp075dFHH53U0JOg3+9LVVXL0uv1RIR3SQhIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABQB0gMAAABFgPQAAABAESA9AAAAUARIDwAAABTB/wOUuANeo9+GJgAAAABJRU5ErkJggg==\" width=\"639.85\">"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib notebook\n",
    "\n",
    "nbins= 200\n",
    "plt.hist(histdata[1].keys().map(float), nbins, weights=histdata[1].values, alpha=0.5, color='r')\n",
    "plt.hist(histdata[0].keys().map(float), nbins, weights=histdata[0].values, alpha=0.8, color='b')\n",
    "plt.yscale('log') # comment this line to obtain linear scale y axis\n",
    "plt.show()"
   ]
  },
  {
   "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.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
