{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Facebook Social Network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "import igraph as ig\n",
    "import dionysus as d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.style.use(\"fivethirtyeight\")\n",
    "plt.rcParams[\"figure.figsize\"] = 10, 6"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data import"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "G = ig.read(\"data/facebook/facebook.graphml\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "G.to_undirected(combine_edges=\"first\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'IGRAPH UN-- 1899 15737 -- \\n+ attr: id (v), name (v), c0 (e), c1 (e), id (e)'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['c0', 'id', 'c1']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G.es.attributes()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "G.es['weight'] = np.array(G.es['c0']).astype(int)\n",
    "G.es['time'] = np.array(G.es['c1']).astype(float)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "del G.es['c0']\n",
    "del G.es['c1']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['time', 'weight', 'id']"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G.es.attributes()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Weight rank clique filtration and persistent homology"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from filtration import wrcf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_diagram(graph, weight=\"weight\"):\n",
    "    filt = wrcf(graph, weight=weight)\n",
    "    pers = d.homology_persistence(filt)\n",
    "    return(d.init_diagrams(pers, filt))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "dgms = get_diagram(G, weight=\"weight\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Diagram with 1899 points,\n",
       " Diagram with 414463 points,\n",
       " Diagram with 39153 points,\n",
       " Diagram with 34 points,\n",
       " Diagram with 0 points,\n",
       " Diagram with 0 points,\n",
       " Diagram with 0 points]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dgms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 29408 characters]\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "d.plot.plot_diagram(dgms[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Normalize the time scale"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 18679088.0)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "time_min = min(G.es[\"time\"])\n",
    "time_max = max(G.es[\"time\"])\n",
    "time_min, time_max"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "G.es[\"time\"] = (np.array(G.es[\"time\"]) - time_min) / (time_max - time_min)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 15344 characters]\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(G.es[\"time\"], bins=50);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Discretize the time scale using non-overlapping windows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 16 # Number of windows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "subgs = list(range(N))\n",
    "for i in range(N):\n",
    "    subgs[i] = G.subgraph_edges(G.es(lambda e: (e[\"time\"] < (i+1)/N) & (e[\"time\"] > i/N)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'IGRAPH UNW- 1899 15737 -- \\n+ attr: id (v), name (v), id (e), time (e), weight (e)'"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "IGRAPH UNW- 2 2 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 35 36 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 742 2455 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 988 3928 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 1121 4569 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 917 2017 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 347 361 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 380 515 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 296 339 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 228 268 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 211 229 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 251 281 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 181 172 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 200 244 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 144 152 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n",
      "IGRAPH UNW- 177 167 -- \n",
      "+ attr: id (v), name (v), id (e), time (e), weight (e)\n"
     ]
    }
   ],
   "source": [
    "for g in subgs:\n",
    "    print(g.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Apply persistent homology to each window"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "from dask.distributed import Client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "client = Client(processes=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "dgms = client.map(get_diagram, subgs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "distributed.comm.inproc - WARNING - Closing dangling queue in <InProc local=inproc://129.67.184.177/21235/7 remote=inproc://129.67.184.177/21235/1>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[[Diagram with 2 points],\n",
       " [Diagram with 35 points, Diagram with 2 points],\n",
       " [Diagram with 742 points,\n",
       "  Diagram with 41706 points,\n",
       "  Diagram with 49 points,\n",
       "  Diagram with 0 points],\n",
       " [Diagram with 988 points,\n",
       "  Diagram with 119949 points,\n",
       "  Diagram with 109 points,\n",
       "  Diagram with 0 points,\n",
       "  Diagram with 0 points],\n",
       " [Diagram with 1121 points,\n",
       "  Diagram with 147710 points,\n",
       "  Diagram with 214 points,\n",
       "  Diagram with 0 points,\n",
       "  Diagram with 0 points],\n",
       " [Diagram with 917 points,\n",
       "  Diagram with 91056 points,\n",
       "  Diagram with 0 points,\n",
       "  Diagram with 0 points],\n",
       " [Diagram with 347 points, Diagram with 12632 points, Diagram with 0 points],\n",
       " [Diagram with 380 points, Diagram with 18081 points, Diagram with 0 points],\n",
       " [Diagram with 296 points, Diagram with 7258 points, Diagram with 0 points],\n",
       " [Diagram with 228 points, Diagram with 5888 points, Diagram with 0 points],\n",
       " [Diagram with 211 points, Diagram with 6965 points, Diagram with 0 points],\n",
       " [Diagram with 251 points, Diagram with 7633 points, Diagram with 0 points],\n",
       " [Diagram with 181 points, Diagram with 3914 points, Diagram with 0 points],\n",
       " [Diagram with 200 points, Diagram with 5267 points, Diagram with 0 points],\n",
       " [Diagram with 144 points, Diagram with 2564 points, Diagram with 0 points],\n",
       " [Diagram with 177 points, Diagram with 2955 points]]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dgms = client.gather(dgms)\n",
    "dgms"
   ]
  },
  {
   "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.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
