{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2ea9834f",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "import pyscisci.all as pyscisci\n",
    "\n",
    "import os\n",
    "import networkx as nx\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pylab as plt\n",
    "\n",
    "\n",
    "try:\n",
    "    import seaborn as sns\n",
    "    sns.set_style('white')\n",
    "    \n",
    "    from cdlib import algorithms\n",
    "    \n",
    "    from clusim.clustering import Clustering\n",
    "except:\n",
    "    print('This example requires the optional packages seaborn, cdlib and clusim.')\n",
    "    print('Please run:')\n",
    "    print('pip install seaborn cdlib clusim')\n",
    "    \n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "bd8c90e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set this path to where the APS database will be stored\n",
    "path2aps = '/home/ajgates/APS'\n",
    "\n",
    "myaps = pyscisci.APS(path2aps, keep_in_memory=False) \n",
    "\n",
    "# override the default APS data with the author disambiguation\n",
    "myaps.set_new_data_path('paa', 'publicationauthoraffiliation_supp2010')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "70937915",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "25f690829fc44f89b89e57b53013ea49",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading Publication Author Affiliation:   0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5e43cb439232468bbe851817a0c78213",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading pub2ref:   0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# we need the linkages between publications and authors\n",
    "paa = myaps.paa\n",
    "\n",
    "# and we need the linkages between publications and their references\n",
    "pub2ref = myaps.pub2ref\n",
    "\n",
    "# finally, we need temporal career information so load the year mapping\n",
    "pub2year = myaps.pub2year\n",
    "\n",
    "# and add the years to the paa\n",
    "paa['Year'] = [pub2year.get(pid, None) for pid in paa['PublicationId'].values]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "23cd1bbd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PublicationId          89\n",
       "AuthorId                1\n",
       "FullName                1\n",
       "AuthorOrder             5\n",
       "OrigAffiliationName    84\n",
       "FirstName               1\n",
       "MiddleName              0\n",
       "LastName                1\n",
       "Year                   22\n",
       "dtype: int64"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Lets take the publication career of Giorgio Parisi\n",
    "\n",
    "parisi_paa = paa[paa['FullName'] == 'giorgio..parisi']\n",
    "parisi_paa.drop_duplicates(subset=['PublicationId'], inplace=True)\n",
    "\n",
    "parisi_paa.nunique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4363f8b2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Graph with 67 nodes and 444 edges\n"
     ]
    }
   ],
   "source": [
    "career_topics, cocite_network = pyscisci.career_cociting_network_topics(parisi_paa, \n",
    "                                                                        pub2ref, \n",
    "                                        randomize=42, \n",
    "                                        return_network=True, show_progress=False)\n",
    "\n",
    "print(nx.info(cocite_network))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "fc31a349",
   "metadata": {},
   "outputs": [],
   "source": [
    "topic_community = nx.get_node_attributes(cocite_network, 'TopicCommunity')\n",
    "\n",
    "louvain_communities = Clustering().from_membership_list([topic_community[i] for i in range(len(topic_community))])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1a9d12a3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 130192 characters]\n",
      "text/plain": [
       "<Figure size 864x864 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "pos = nx.drawing.nx_agraph.graphviz_layout(cocite_network, prog='sfdp',)\n",
    "\n",
    "\n",
    "fig, ax = plt.subplots(1,1,figsize=(12,12))         \n",
    "\n",
    "\n",
    "\n",
    "nx.draw_networkx_edges(cocite_network, pos, edgelist=cocite_network.edges(),\n",
    "        edge_color = '0.4',\n",
    "        alpha=0.2,\n",
    "        ax=ax)\n",
    "\n",
    "for c in louvain_communities.clusters:\n",
    "    nx.draw_networkx_nodes(cocite_network.subgraph(louvain_communities.clu2elm_dict[c]), pos,\n",
    "        node_size= 100, \n",
    "        node_color=[c]*len(louvain_communities.clu2elm_dict[c]),\n",
    "        cmap = sns.color_palette(\"Set2\", as_cmap=True),\n",
    "        edgecolors='0.2', # node outline\n",
    "        vmin = 0,\n",
    "        vmax = louvain_communities.n_clusters,\n",
    "        label = str(c),\n",
    "        ax = ax)\n",
    "\n",
    "\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "3501b0b6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ncomm = louvain_communities.n_clusters\n",
    "community_connectivity = np.zeros((ncomm, ncomm))\n",
    "\n",
    "cociting_adjmat = nx.to_scipy_sparse_matrix(cocite_network)\n",
    "\n",
    "for ic, jc in itertools.product(range(ncomm), repeat=2):\n",
    "    idx = np.sort(list(louvain_communities.clu2elm_dict[ic]))\n",
    "    jdx = np.sort(list(louvain_communities.clu2elm_dict[jc]))\n",
    "    community_connectivity[ic,jc] = cociting_adjmat[idx][:,jdx].sum()\n",
    "\n",
    "community_connectivity = community_connectivity/community_connectivity.sum(axis=0)\n",
    "\n",
    "fig, ax = plt.subplots(1,1,figsize=(6,6))\n",
    "\n",
    "ax.imshow(community_connectivity, cmap='YlOrRd', vmin=0, vmax=1)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b0f1a007",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 14672 characters]\n",
      "text/plain": [
       "<Figure size 720x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "cmap = sns.color_palette(\"Set2\", as_cmap=True)\n",
    "\n",
    "fig, ax = plt.subplots(1,1,figsize=(10, 4))\n",
    "\n",
    "for y, topic, degree in career_topics[['Year', 'TopicCommunity', 'Degree']].values:\n",
    "    ax.scatter(y, degree, c=[topic], cmap=cmap, vmin=0, alpha=0.8,\n",
    "               vmax=louvain_communities.n_clusters, zorder=5)\n",
    "    ax.plot([y,y], [0,degree], color='k', lw=0.25, zorder=4)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "222adb2a",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
