{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a0df6b80-19ba-4156-8c4d-9300880c11cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "install.packages(\"devtools\")\n",
    "library(devtools)\n",
    "devtools::install_local('/home/jovyan/gganimate-0.1.1.tar.gz')\n",
    "devtools::install_local('/home/jovyan/ggraph-d15fd149babe9ad32316474b9a178e019f376ba6.zip')\n",
    "library(gganimate)\n",
    "library(ggraph)\n",
    "library(igraph)\n",
    "library(RColorBrewer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4e87fb8-b58e-4309-adfc-2a7cfe9afbd8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Originally for data from http://konect.uni-koblenz.de/networks/sociopatterns-infectious\n",
    "# as part of a museum exhibit on spread of infections http://www.sociopatterns.org/deployments/infectious-sociopatterns/\n",
    "# and the paper http://www.sociopatterns.org/publications/whats-in-a-crowd-analysis-of-face-to-face-behavioral-networks/\n",
    "\n",
    "# Code adapted from https://gist.github.com/thomasp85/eee48b065ff454e390e1\n",
    "# and from https://gist.github.com/jalapic/612036977d9f9c773107681bc4a46d58\n",
    "\n",
    "infect <- read.table('/home/jovyan/networkDynamicsLabels.txt', skip = 0, sep = ' ', stringsAsFactors = FALSE)\n",
    "infect$V3 <- NULL \n",
    "names(infect) <- c('from', 'to', 'time')\n",
    "infect$timebins <- as.numeric(cut(infect$time, breaks = 150)) # lower means more bursty, i.e. breaks = 10\n",
    "\n",
    "# We want that nice fading effect so we need to add extra data for the trailing\n",
    "infectAnim <- lapply(1:10, function(i) {infect$timebins  <- infect$timebins + i; infect$delay <- i; infect})\n",
    "infect$delay <- 0\n",
    "infectAnim <- rbind(infect, do.call(rbind, infectAnim))\n",
    "\n",
    "infectGraph <- graph_from_data_frame(infectAnim, directed = F)\n",
    "\n",
    "# We use only original data for the layout\n",
    "subGr <- subgraph.edges(infectGraph, which(E(infectGraph)$delay == 0))\n",
    "V(subGr)$degree <- degree(subGr)\n",
    "V(subGr)$group <- cluster_louvain(subGr)$membership\n",
    "lay <- createLayout(subGr, 'igraph', algorithm = 'fr') # change spatial layout of network\n",
    "\n",
    "# Then we reassign the full graph with edge trails\n",
    "attr(lay, 'graph') <- infectGraph\n",
    "\n",
    "# Now we create the graph with timebins as frame\n",
    "p <- ggraph(data = lay, layout = 'fr', aes(frame = timebins)) + \n",
    "  geom_node_point(size = .025, col = \"white\") + # change size & color of inactive nodes\n",
    "  geom_node_point(aes(alpha=0.6), size = .025, colour = factor(lay$group), show.legend = FALSE) + # change size & color of active nodes\n",
    "  # geom_edge_link0(aes(frame = timebins, alpha = delay, width = delay), edge_colour = '#dccf9f') + \n",
    "  geom_edge_link0(aes(frame = timebins, alpha = delay, width = delay, colour = factor(node1.group)), data = gEdges(nodePar = 'group'), show.legend = FALSE) +\n",
    "  # geom_edge_link0(aes(frame = timebins, alpha = delay, width = delay, colour = node1.degree), data = gEdges(nodePar = 'degree'), show.legend = FALSE) +\n",
    "  scale_edge_alpha(range = c(1, 0), guide = 'none') + \n",
    "  scale_edge_width(range = c(0.25, 0.75), trans = 'exp', guide = 'none') + # change edge width\n",
    "  scale_size(guide = 'none') + \n",
    "  expand_limits(x = c(min(lay$x), max(lay$x)), y = c(min(lay$y), max(lay$y))) +\n",
    "  ggforce::theme_no_axes() + \n",
    "  theme(plot.background = element_rect(fill = '#000000'), # change background color\n",
    "        panel.background = element_blank(), \n",
    "        panel.border = element_blank(), \n",
    "        plot.title = element_text(color = '#cecece'))\n",
    "\n",
    "infect"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "049bdcfe-7af0-4876-8f4b-fee828c265ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Note if the animation surpasses the memory usage of the notebook, it will crash.\n",
    "# reduce memory by changing image size, image resolution, making network smaller, \n",
    "# changing interval, and/or changing breaks\n",
    "\n",
    "# And then we animate\n",
    "animation::ani.options(interval=0.01) # change speed of frame transitions\n",
    "\n",
    "gganim <- gganimate(p, '/home/jovyan/sparkingCuriosity.gif', title_frame = FALSE,\n",
    "         ani.width = 400, ani.height = 400, res=100) # change image size and resolution\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "codemirror_mode": "r",
   "file_extension": ".r",
   "mimetype": "text/x-r-source",
   "name": "R",
   "pygments_lexer": "r",
   "version": "4.0.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}